Skip to content
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

Don't raise ActionController::UnknownHttpMethod from ActionDispatch::Static #25798

Merged
merged 1 commit into from
Jul 14, 2016
Merged

Don't raise ActionController::UnknownHttpMethod from ActionDispatch::Static #25798

merged 1 commit into from
Jul 14, 2016

Conversation

greysteil
Copy link
Contributor

The ActionDispatch::Static middleware is used low down in the stack to serve static assets before doing much processing. Since it's called from so low in the stack, we don't have access to the request ID at this point, and generally won't have any exception handling defined (by default ShowExceptions is added to the stack quite a bit higher and relies on logging and request ID).

Before 8f27d60 this middleware would ignore unknown HTTP methods, and an exception about these would be raised higher in the stack. After that commit, however, that exception will be raised here.

If we want to keep ActionDispatch::Static so low in the stack (I think we do) we should suppress theActionController::UnknownHttpMethod` exception here, and instead let it be raised higher up the stack, once we've had a chance to define exception handling behaviour.

@rails-bot
Copy link

r? @sgrif

(@rails-bot has picked a reviewer for you, use r? to override)

@matthewd
Copy link
Member

Can we use Rack::Request here instead? I haven't read closely, but it seems plausible that we may not be relying on any AD::Request-specific behaviours.

@greysteil
Copy link
Contributor Author

greysteil commented Jul 12, 2016

We use request.accept_encoding in ActionDispatch::FileHandler#serve, which is ActionDispatch::Request specific.

We could do the following, if it's preferable?

def call(env)
  req = Rack::Request.new env

  if req.get? || req.head?
    path = req.path_info.chomp('/'.freeze)
    if match = @file_handler.match?(path)
      req.path_info = match
      return @file_handler.serve(ActionDispatch::Request.new(env))
    end
  end

  @app.call(req.env)
end

@tenderlove
Copy link
Member

@greysteil ya, lets go with Rack::Request. I think we pushed accept_encoding up in Rack, so maybe we could get away with a Rack::Request in file handler. Would you mind trying it out?

@greysteil
Copy link
Contributor Author

@matthewd @tenderlove - updated. Rack::Request does indeed implement accept_encoding, but returns an array, rather than a string - hence the change to gzip_encoding_accepted?.

@@ -160,6 +160,9 @@ def test_serves_gzip_files_when_header_set
response = get(file_name, 'HTTP_ACCEPT_ENCODING' => 'GZIP')
assert_gzip file_name, response

response = get(file_name, 'HTTP_ACCEPT_ENCODING' => 'compress;q=0.5, gzip;q=1.0')
Copy link
Contributor Author

@greysteil greysteil Jul 13, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We didn't have any tests where gzip wasn't the first content-coding, but now we're using the parsed accept encoding (rather than the raw string) it feels valuable to check this case.

…Static

The `ActionDispatch::Static` middleware is used low down in the stack to serve
static assets before doing much processing. Since it's called from so low in
the stack, we don't have access to the request ID at this point, and generally
won't have any exception handling defined (by default `ShowExceptions` is added
to the stack quite a bit higher and relies on logging and request ID).

Before 8f27d60
this middleware would ignore unknown HTTP methods, and an exception about these
would be raised higher in the stack. After that commit, however, that exception
will be raised here.

If we want to keep `ActionDispatch::Static` so low in the stack (I think we do)
we should suppress the `ActionController::UnknownHttpMethod` exception here,
and instead let it be raised higher up the stack, once we've had a chance to
define exception handling behaviour.

This PR updates `ActionDispatch::Static` so it passes `Rack::Request` objects to
`ActionDispatch::FileHandler`, which won't raise an
`ActionController::UnknownHttpMethod` error. If an unknown method is
passed, it should exception higher in the stack instead, once we've had a
chance to define exception handling behaviour.`
@greysteil
Copy link
Contributor Author

Just rebased off master to fix a changelog conflict, and specs are 💚 . Hopefully this is good to go now.

@sgrif
Copy link
Contributor

sgrif commented Jul 13, 2016

r? @matthewd

@rails-bot rails-bot assigned matthewd and unassigned sgrif Jul 13, 2016
@matthewd matthewd merged commit a1ac08c into rails:master Jul 14, 2016
@greysteil
Copy link
Contributor Author

❤️ - thanks guys.

@greysteil greysteil deleted the dont-raise-unknown-http-method-low-in-stack branch July 14, 2016 08:55
rafaelfranca pushed a commit that referenced this pull request Jul 17, 2016
…od-low-in-stack

Don't raise ActionController::UnknownHttpMethod from ActionDispatch::Static
@rafaelfranca
Copy link
Member

Backported in ffa13e9

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants