-
Notifications
You must be signed in to change notification settings - Fork 283
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
get session from env instead of request #586
Conversation
@@ -201,8 +201,8 @@ def rollbar_route_params(env) | |||
end | |||
end | |||
|
|||
def rollbar_request_session(rack_req) | |||
session = rack_req.session |
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.
Okay so the way I read the Rack::Request code is that this line is roughly equivalent to
session = env.fetch('rack.session', nil)
if session.nil?
env['rack.session'] = {}
session = env['rack.session']
end
In other words, Rack::Request modifies the underlying env
by setting the rack.session
header if it is missing. So using the Rack::Request to pull the session introduces an ordering issue into the middleware.
def rollbar_request_session(rack_req) | ||
session = rack_req.session | ||
def rollbar_request_session(env) | ||
session = env.fetch('rack.session', {}) |
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.
We just want the session, but we don't want to modify the underlying env
, so in theory this will fetch the same value that rack_req.session
does if it is already set, otherwise it returns an empty hash if it is not set (which is the same as rack_req.session
). The only difference is that env['rack.session']
does not get set to {}
if it was undefined.
I think this is a good change, it removes the side effect of modifying the environment due to our session access. This leads me to the additional question of whether we should be using the env to access the cookies directly via |
Is there a simple example reproduction of what bug this is causing? I am see that there is an ordering issue with the middlewares, but can you describe the specific series of events that leads to hitting this? It would be useful for making a test so that it is clear why we are using the env directly. @jondeandres do you have any insight into why we are using |
I think we would need to know the exact problems that this is causing because it doesn't look to be an error in our side. We are using the request object where we can because it encapsulates the logic to access its data. In the case of fetching |
Here's a callstack emanating from a call to
@jondeandres This isn't the only situation I've seen where using the request objects in middleware can cause unrecoverable errors (because they mutate the I created a rails app as a minimal reproducible example: https://github.com/zvkemp/rollbar-session-repro. This is a plain rails app (-ActiveRecord, +Rollbar). Only code modifications are in https://github.com/zvkemp/rollbar-session-repro/blob/master/config/initializers/session_store.rb. |
Oh, and the error you should expect to see when you request I also tested using Rails's default cookie store. To reproduce, change the last portions of config/initializers/session_store: Rails.application.config.session_store :cookie_store, key: '_rollbar_session_repro_session'
Rails.application.middleware.insert_before(
ActionDispatch::Session::CookieStore,
WarningMiddleware
) In this case, the error is |
I would almost argue this is buggy behaviour on the part of both Rack and ActionDispatch. The stacktrace using the plain cookie store:
Makes me think that actionpack and rack made assumptions they should not have considering the use of inheritance here. The call to We can "fix" this on our side by not modifying the environment which is what this PR does, but this is a really shitty thing that actionpack does. |
Yes, I completely agree. There is a lot of logic in ActionDispatch/Rack that appears to have been intended to mitigate this issue (the whole 'merge original session' logic that pops up in a few places), but it doesn't cover all of the cases (to wit, this PR). |
Let's merge this, it is a reasonable fix to a bad situation caused by ActionDispatch and Rack. |
Rack::Session
andActionDispatch::Session
populateenv['rack.session']
with an empty hash unless another value has already been set (e.g., a session object). If any errors are rescued or reported in middleware between Rollbar's middleware and the default Rails session initialization middleware, this value would have been set, and will create issues when trying to prepare the session later on. I.e., calling Rollbar too early nukes the request by mutating the env.Issue found on Rack 1.5.5, Rails 4.1.16. Newer versions of Rack also set this default value (but in a slightly different way), so it should apply there as well.