-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Avoid multiple mount pollution #2612
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Avoid multiple mount pollution #2612
Conversation
|
@alexanderadam Thanks! Fix CI/CHANGELOG and I'll take a close look - @ericproulx wdyt? |
2cd43bb to
1856ff9
Compare
done 🙂 |
1856ff9 to
0660ae7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
0660ae7 to
68a36c8
Compare
|
That's fine to me if it fixes the issue. The test looks perfectly right. |
|
Looks good to me 👍 thank you |
|
@alexanderadam could you mount your api multiple times and try with a configuration. |
|
@alexanderadam see my comment on breaking up specs, too, please. |
I don't have a production API (the ticket creator is @bogdan — and I also think it would be good if @bogdan could check whether this fixes it 😉 ) but I created a test script doing the two variants where we always send require 'grape'
require 'rack/mock'
module BuggyBehavior
def call(env)
(never_mounted? ? base_instance : mounted_instances.first).call(env)
end
end
Grape::API.singleton_class.prepend(BuggyBehavior)
api1 = Class.new(Grape::API) do
format :json
version 'v1', using: :path
resource(:system) { get(:ping) { { message: 'pong' } } }
end
parent1 = Class.new(Grape::API) { namespace('/api') { mount api1 } }
parent2 = Class.new(Grape::API) { mount api1 }
status_via_parent1, * = parent1.call(Rack::MockRequest.env_for('/v1/api/system/ping', method: 'GET'))
status_via_parent2, * = parent2.call(Rack::MockRequest.env_for('/v1/system/ping', method: 'GET'))
status_direct, * = api1.call(Rack::MockRequest.env_for('/v1/system/ping', method: 'GET'))
puts "Without fix via parent1 => /v1/api/system/ping => #{status_via_parent1} #{status_via_parent1 == 200 ? 'All good' : 'Sad server noises'}"
puts "Without fix via parent2 => /v1/system/ping => #{status_via_parent2} #{status_via_parent2 == 200 ? 'All good' : 'Sad server noises'}"
puts "Without fix directly => /v1/system/ping => #{status_direct} #{status_direct == 200 ? 'All good' : 'Sad server noises - polluted'}"
api2 = Class.new(Grape::API) do
format :json
version 'v1', using: :path
resource(:system) { get(:ping) { { message: 'pong' } } }
end
def api2.call(env) = base_instance.call(env)
parent3 = Class.new(Grape::API) { namespace('/api') { mount api2 } }
parent4 = Class.new(Grape::API) { mount api2 }
status_via_parent3, * = parent3.call(Rack::MockRequest.env_for('/v1/api/system/ping', method: 'GET'))
status_via_parent4, * = parent4.call(Rack::MockRequest.env_for('/v1/system/ping', method: 'GET'))
status_direct2, * = api2.call(Rack::MockRequest.env_for('/v1/system/ping', method: 'GET'))
puts "With fix via parent1 => /v1/api/system/ping => #{status_via_parent3} #{status_via_parent3 == 200 ? 'All good' : 'Sad server noises'}"
puts "With fix via parent2 => /v1/system/ping => #{status_via_parent4} #{status_via_parent4 == 200 ? 'All good' : 'Sad server noises'}"
puts "With fix directly => /v1/system/ping => #{status_direct2} #{status_direct2 == 200 ? 'All good' : 'Sad server noises'}"Its output looks like this:
✔️ |
68a36c8 to
342b987
Compare
|
I tried to test it with my project, but this patch branch is not compatible with grape-swagger: |
|
@alexanderadam Do we capture all the scenarios from your example in tests? if not please add @bogdan removal of |
Yes, it would have made me feel better.
I don't know. Do you have something particular in mind? |
|
I'm merging this, thanks everyone. Looks like someone will followup on ruby-grape/grape-swagger#965. |
Soooo, I might have missed something here but the way I see this is, that PR #1893 introduced the behaviour seen in #2576.
And the problem to be tackled was different than what was implemented.
According to the Rack Spec, a Rack app only needs to be
Therefore having
Grape::API.calldelegating tobase_instance.callshould be enough.Howeveeeeeer, when using
Rack::Testwith def app returning aGrape::APIclass directly (e.g.,API::V1::Ping), tests would naturally fail with404.So to me this looks like the fix with d29eb79 was a bit weird and introduced that bug in #2576. 🤔
But I could also be totally wrong with my understanding here.
And I'm therefore open to any corrections and learnings.
PS: I'm looking for a new adventure in case anybody is looking to hire or work with a Ruby/Rails/Crystal dev
PPS: would you be so kind and add the
hacktoberfest-acceptedlabel to this issue in case you find that PR helpful? 🥺