Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
* [#2605](https://github.com/ruby-grape/grape/pull/2605): Add Rack 3.2 support with new gemfile and CI integration - [@ericproulx](https://github.com/ericproulx).
* [#2607](https://github.com/ruby-grape/grape/pull/2607): Remove namespace_stackable and namespace_inheritable from public API - [@ericproulx](https://github.com/ericproulx).
* Your contribution here.
* [#2612](https://github.com/ruby-grape/grape/pull/2612): Avoid multiple mount pollution - [@alexanderadam](https://github.com/alexanderadam).

#### Fixes

Expand Down
13 changes: 2 additions & 11 deletions lib/grape/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,13 @@ class << self
attr_accessor :base_instance, :instances

delegate_missing_to :base_instance
def_delegators :base_instance, :new, :configuration

# This is the interface point between Rack and Grape; it accepts a request
# from Rack and ultimately returns an array of three values: the status,
# the headers, and the body. See [the rack specification]
# (http://www.rubydoc.info/github/rack/rack/master/file/SPEC) for more.
# (https://github.com/rack/rack/blob/main/SPEC.rdoc) for more.
# NOTE: This will only be called on an API directly mounted on RACK
def_delegators :instance_for_rack, :call, :compile!
def_delegators :base_instance, :new, :configuration, :call, :compile!

# When inherited, will create a list of all instances (times the API was mounted)
# It will listen to the setup required to mount that endpoint, and replicate it on any new instance
Expand Down Expand Up @@ -95,14 +94,6 @@ def replay_setup_on(instance)
end
end

def instance_for_rack
if never_mounted?
base_instance
else
mounted_instances.first
end
end

# Adds a new stage to the set up require to get a Grape::API up and running
def add_setup(step)
@setup << step
Expand Down
22 changes: 0 additions & 22 deletions spec/grape/api_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1055,28 +1055,6 @@ def to_txt
end
end

# NOTE: this method is required to preserve the ability of pre-mounting
# the root API into a namespace, it may be deprecated in the future.
describe 'instance_for_rack' do
context 'when the app was not mounted' do
it 'returns the base_instance' do
expect(app.__send__(:instance_for_rack)).to eq app.base_instance
end
end

context 'when the app was mounted' do
it 'returns the first mounted instance' do
mounted_app = app
Class.new(described_class) do
namespace 'new_namespace' do
mount mounted_app
end
end
expect(app.__send__(:instance_for_rack)).to eq app.__send__(:mounted_instances).first
end
end
end

describe 'filters' do
it 'adds a before filter' do
subject.before { @foo = 'first' }
Expand Down
44 changes: 44 additions & 0 deletions spec/grape/integration/rack_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,48 @@
expect(last_response).to be_successful
end
end

# https://github.com/ruby-grape/grape/issues/2576
describe 'when an api is mounted' do
let(:api) do
Class.new(Grape::API) do
format :json
version 'v1', using: :path

resource :system do
get :ping do
{ message: 'pong' }
end
end
end
end

let(:parent_api) do
api_to_mount = api
Class.new(Grape::API) do
format :json
namespace '/api' do
mount api_to_mount
end
end
end

it 'is not polluted with the parent namespace' do
env = Rack::MockRequest.env_for('/v1/api/system/ping', method: 'GET')
response = Rack::MockResponse[*parent_api.call(env)]

expect(response.status).to eq(200)
parsed_body = JSON.parse(response.body)
expect(parsed_body['message']).to eq('pong')
end

it 'can call the api' do
env = Rack::MockRequest.env_for('/v1/system/ping', method: 'GET')
response = Rack::MockResponse[*api.call(env)]

expect(response.status).to eq(200)
parsed_body = JSON.parse(response.body)
expect(parsed_body['message']).to eq('pong')
end
end
end