ruby-grape / grape

An opinionated framework for creating REST-like APIs in Ruby.
http://www.ruby-grape.org
MIT License
9.88k stars 1.22k forks source link

Use custom middleware only for special routes #712

Open dspaeth-faber opened 10 years ago

dspaeth-faber commented 10 years ago

Hi,

at the moment when you use the use statement you include your middleware for the actual namespace and childrens of your namespace. For some middlewares thats not what you want. For instance authentication middleware should only be included for your current route or up to the end of your namespace.

I think it would be nice do extend the use statement with an option to configure the scope to which this middleware should be applied.

A block for use can't be used because this block is applied to the middleware class.

dblock commented 10 years ago

Maybe a non-recursive use could be called something else, like mount or inline? Semantically Rack middleware always applies to everything "underneath".

dspaeth-faber commented 10 years ago

| Semantically Rack middleware always applies to everything "underneath".

But grape handle it a little bit different. Every middleware is added directly to an endpoint. So from my point of view it makes sence to provide such a feature.

I would like to implement it, but scope of settings is not clear to me. There are settings. settings.imbue and so on.

It would be nice if there is a developer documentation which explains for what scope what to use.

maybe a dsl like this is possible:


class API < Grape::API

  use MyMiddleware do
    action do
        # the proc for the middleware
    end

    get ... do
     end
 end

end
dblock commented 10 years ago

The whole imbue thing precedes me :) Feel free to document!

dspaeth-faber commented 10 years ago

If I could I would. But to get this done I would need to step with pry through all the code. It would be good when some one with knowlege about the code can document the scope of settings and options.

dspaeth-faber commented 10 years ago

Is this right about scopes?

dspaeth-faber commented 10 years ago

Maybe this are the needed scopes:


class Setting
   # valid for all API classes doesn't matter where set
   # example 'logger'
   def self.global
   end

   # only for next route 
   # reseted with next route or new namespace 
   # example 'desc' (for route)
   def self.route
   end

   # valid only for the current namespace
   # not for parrents or children
   # example 'desc' (for namespace)
   def self.namespace
   end

   # valid for current namespace and children
   # can be overrwriten in child namespace
   # example 'version'
   def self.namespace_inheritable
   end

   # valid for current namespace
   # settings in child namespaces are added
   # example 'before'
   def self.namespace_stackable
   end
end
dblock commented 10 years ago

Looks right re: scopes.

antek-drzewiecki commented 10 years ago

What also would be awesome, is when adding authentication middleware, that you can easily define helper methods that can be used in your endpoint later on. Lets say the current user or something. But then again that shouldn't be the responsibility of the middleware, should it?

dspaeth-faber commented 10 years ago

A middleware specific to grape has always the possibility to add methods to the actual Endpoint:


class MyMiddleware
  module SomeMethods
     ...
  end

  def call(env)
    env['api.endpoint'].extend(SomeMethods)
   @app.call(env)
  end
end 
dspaeth-faber commented 10 years ago

@dblock in this branch I did some refactoring with settings. Can you please so kind and look into it? At the current state I don't want to create PR but would like to here your opinion.

Edit: It's now a PR #739

dblock commented 10 years ago

@dspaeth-faber Took a look at your branch. I think naming is a lot better - I mean 'imbue' was never something I understood :) Seems like there's a bit more code, but it's focused, so I like it. I even wonder whether this part of the DSL is something useful for other gems!

dspaeth-faber commented 10 years ago

I'm glad to hear this :)