ruby-grape / grape

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

Accessing @env inside Grape::DSL::Extensions #1094

Open railsmith opened 9 years ago

railsmith commented 9 years ago

Can we access env before the endpoint? Accessing env inside the endpoint works but accessing it inside a DSL extension does not. Is this feature supported?

module Grape
   module Extensions
    def special_scope
       @env
    end

    Grape::API.extend self
  end
 end

I need a custom DSL to be added around the grape endpoints which gives me access to env variable.

 resources :users
   special_scope
     get /users do
     end
  end
dblock commented 9 years ago

We should be able to make it work, however I am not sure of the scope of that @env. If you can build a failing test case in Grape I could try to play with it.

railsmith commented 9 years ago

https://github.com/ruby-grape/grape/pull/1095

I hope you can understand what I am trying to do. Please see environment_spec.rb.

railsmith commented 9 years ago

For now I have monkey patched antek-drzewiecki/wine_bouncer as the issue was with WineBouncer and not with Grape.

dblock commented 9 years ago

@harshitsk Can you please elaborate? Should we close this?

railsmith commented 9 years ago

In our application we have mounted Grape on Rails and we are using Doorkeeper + WineBouncer to protect our endpoints.

I wanted to pass some special scopes to WineBouncer at runtime.

   oauth2  'r_admin', 'w_admin', special_scope
    get '/hello' do
    { "hello world" }
    end

Therefore I asked for a custom DSL in Grape where we can access the Grape environment information before it hits the endpoint. After looking at the Grape code base it seems that we cannot do this without the Grape::Middleware::Base hence I modified WineBouncer::Oauth2 which is derived from Grape::Middleware::Base.

If you think this is an important feature that Grape should support then you can play around it to work it out otherwise you can close this.

dblock commented 9 years ago

I think it's a useful feature, lets leave this open.

pboling commented 4 years ago

It seems like this feature is a requirement of API testing with Devise and/or Omniauth.

Example is for Rails, where access to request.env is available.

before do 
  request.env["devise.mapping"] = Devise.mappings[:user] # If using Devise
  request.env["omniauth.auth"] = OmniAuth.config.mock_auth[:twitter] 
end

Is this possible in current Grape?

dblock commented 4 years ago

Is this possible in current Grape?

This issue is pretty old. Can you please try @pboling and see if env is available as is and whether you can do this?

pboling commented 4 years ago

@dblock I am still digging through source code, and trying to understand how everything fits together, but so far I have not been able to. I think this is more because request is not available from within the scope of a spec. There is a header macro (I think this comes from rack-test) to set headers for a subsequent request... which is similar to, but not the same as, what the documentation is asking for.

If I need to set something inside the request.env prior to the request, I am not sure how I would do that, as requested by the omniauth testing documentation.

At the same time it makes no sense to me why this would be needed at all, because it seems that request.env data should be set by the middleware. Is it because the middleware is being skipped? Are grape functional tests not sending real requests, but more like Rails controller tests, a little bit fake?

Bottom line is - I don't know how to write a functional spec with Grape + Omniauth, and I'm not sure it is even possible (easily, anyway).

dblock commented 4 years ago

Can you maybe try to add a generic failing spec in https://github.com/ruby-grape/grape/tree/master/spec/integration that brings omniauth in and demonstrates how it doesn't work? I can then try and take a look. Those integration specs have their own Gemfile.