ohler55 / agoo

A High Performance HTTP Server for Ruby
MIT License
912 stars 39 forks source link

Can you tell me how I can use agoo with rack middleware? #90

Closed mxvanzant closed 4 years ago

mxvanzant commented 4 years ago

Hi! I'd like to use agoo as my server, but I could not see how to plug in some rack middlewares to run before the agoo handlers. Is this possible? Thanks, Mike.

ohler55 commented 4 years ago

Yes it is possible. I appologize ahead of time in case I start out describing things you already know. Middleware is really just a wrapper around your app. For if you have a class called MyApp it will have a #call(env) method. Rack middleware also implements the same #call(env) but inside that method it will call MyApp.call(env). So the middleware object just need to be initialized with an instance of MyApp and then make the Agoo handler the middleware.

If you have a suggestion for being more conformant with common practices please let me know. I tend to b more of a tool writer and fall short on following the use cases more than I should.

mxvanzant commented 4 years ago

thx! I will try as you suggest and see if I understand correctly (I'll let you know later tonight or tomorrow). Best Regards.

mxvanzant commented 4 years ago

Hi Peter,

From what I've seen, middleware classes implement #call(env), but they also handle calling the next middleware.

For example, in this code snippet you will see the call to @app.call(env) within this middlewares #call method:

  module Rack
    class JsonBodyParser
      def initialize(app, symbolize_names=false)
        @app = app
        @symbolize_names = symbolize_names
      end
      def call(env)
        # do some stuff..
        @app.call(env)
      end
    end

In my code here:

    Agoo::Server.init(9292, public_dir())

    Agoo::Server.handle(:GET, "/", Api.method(:default))
    Agoo::Server.handle(:GET, "/app", Api.method(:app))
    Agoo::Server.handle(:GET, "/app/**", -> (env){
      req = Env.prep(env)
      [200, {}, ["bbb\n", req.env['PATH_INFO']]]
    })

    Agoo::Server.start()

I'm initializing the agoo server and adding several handlers and then starting the server, but I would like to have some middlewares run before the my agoo handlers. Maybe I can use rackup with a .ru file? But I'm not understanding how. (Agoo is both a server and a rack handler?)

I've done something like this with Sinatra, but I'm not sure how to do something similar with agoo:

require 'logger'
require 'rack_json_body_parser'

logger = Logger.new(STDOUT)
use Rack::CommonLogger, logger
use Rack::PostBodyContentTypeParser, true
run MySinatraClass

Maybe you can show me a simple example of how I would do this with multiple agoo handlers?

Sorry if these are basic questions.

Thanks, Mike

ohler55 commented 4 years ago

Agoo is both a server and rack handler. It does implement everything required in the Rack spec. Currently it does not implement the use function. Now that you have identified that I will add that this week. Until then you can do the same thing the the use function would do.

app = JsonBodyParser.new(my_app)
Agoo::Server.handle(:GET, '/app', app)

Something like that. I need to do a little checking to make sure I understand how order matters with the use function and also with the argument to it but otherwise it looks pretty straight forward to add.

mxvanzant commented 4 years ago

Thanks Peter -- 'use' will be very nice to have! For now, I will do something like you have suggested.

ohler55 commented 4 years ago

Finally able to really dig into this. I realized that if you use config.ru the use() function works fine but of course you then get the Rack overhead. So my plan no is to implement an Agoo::Server::use() function that does the same thing as the Rack use() function.

mxvanzant commented 4 years ago

Awesome! Yes, I believe that was my quandary. Looking forward to it. Thank you!

ohler55 commented 4 years ago

There is a branch called 'rack-use' that includes a new Agoo::Server.use() function. An example is at example/use/use.rb. I still need to add a README but it should be pretty to understand with the example.

mxvanzant commented 4 years ago

Thank you Peter -- I will try this out!!

ohler55 commented 4 years ago

Great, let me know what you think.

ohler55 commented 4 years ago

Okay to close this?

mxvanzant commented 4 years ago

Sorry Peter, I had put this project on the back burner for a while, but I have some time now and will test it out and let you know how it works soon. Thank you.

mxvanzant commented 4 years ago

Yes. This works great! Thanks!