Skip to content

Fix {Public,Debug}Exceptions rendering body for HEAD #55149

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

Merged
merged 1 commit into from
Jun 5, 2025

Conversation

skipkayhil
Copy link
Member

Fix #55131

Rack::Lint already errors in this case, it just wasn't being covered.

Error:
DebugExceptionsTest#test_returns_empty_body_on_HEAD_cascade_pass:
Rack::Lint::LintError: Response body was given for HEAD request, but should be empty
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-3.1.15/lib/rack/lint.rb:773:in 'Rack::Lint::Wrapper#verify_content_length'
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-3.1.15/lib/rack/lint.rb:899:in 'Rack::Lint::Wrapper#each'
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-3.1.15/lib/rack/response.rb:345:in 'Rack::Response::Helpers#buffered_body!'
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-3.1.15/lib/rack/mock_response.rb:65:in 'Rack::MockResponse#initialize'
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-test-2.2.0/lib/rack/test.rb:362:in 'Class#new'
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-test-2.2.0/lib/rack/test.rb:362:in 'Rack::Test::Session#process_request'
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-test-2.2.0/lib/rack/test.rb:153:in 'Rack::Test::Session#request'
    lib/action_dispatch/testing/integration.rb:297:in 'ActionDispatch::Integration::Session#process'
    lib/action_dispatch/testing/integration.rb:49:in 'ActionDispatch::Integration::RequestHelpers#head'
    lib/action_dispatch/testing/integration.rb:388:in 'ActionDispatch::Integration::Runner#head'
    test/dispatch/debug_exceptions_test.rb:189:in 'block in <class:DebugExceptionsTest>'

Error:
ShowExceptionsTest#test_rescue_with_no_body_for_HEAD_requests:
Rack::Lint::LintError: Response body was given for HEAD request, but should be empty
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-3.1.15/lib/rack/lint.rb:773:in 'Rack::Lint::Wrapper#verify_content_length'
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-3.1.15/lib/rack/lint.rb:900:in 'Rack::Lint::Wrapper#each'
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-3.1.15/lib/rack/response.rb:345:in 'Rack::Response::Helpers#buffered_body!'
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-3.1.15/lib/rack/mock_response.rb:65:in 'Rack::MockResponse#initialize'
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-test-2.2.0/lib/rack/test.rb:362:in 'Class#new'
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-test-2.2.0/lib/rack/test.rb:362:in 'Rack::Test::Session#process_request'
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-test-2.2.0/lib/rack/test.rb:153:in 'Rack::Test::Session#request'
    lib/action_dispatch/testing/integration.rb:297:in 'ActionDispatch::Integration::Session#process'
    lib/action_dispatch/testing/integration.rb:49:in 'ActionDispatch::Integration::RequestHelpers#head'
    lib/action_dispatch/testing/integration.rb:388:in 'ActionDispatch::Integration::Runner#head'
    test/dispatch/show_exceptions_test.rb:73:in 'block in <class:ShowExceptionsTest>'

Checklist

Before submitting the PR make sure the following are checked:

  • This Pull Request is related to one change. Unrelated changes should be opened in separate PRs.
  • Commit message has a detailed description of what changed and why. If this PR fixes a related issue include it in the commit message. Ex: [Fix #issue-number]
  • Tests are added or updated if you fix a bug or add a feature.
  • CHANGELOG files are updated for the changed libraries if there is a behavior change or additional feature. Minor bug fixes and documentation changes should not be included.

@rails-bot rails-bot bot added the actionpack label Jun 4, 2025
response = @exceptions_app.call(request.env)
response[1][Constants::X_CASCADE] == "pass" ? pass_response(status) : response

if response[1][Constants::X_CASCADE] == "pass" || head_request
Copy link
Member

@Edouard-chin Edouard-chin Jun 4, 2025

Choose a reason for hiding this comment

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

I think this should belong in the PublicException app, otherwise we'd be discarding custom headers sent by a custom PublicException app (We'd just send the X_CASCADE header).

Another small benefit if we move this in the PublicException app is that we won't need to render the template since we don't need it.

The downside is that application will have to implement this in their PublicException app if they use a custom one.

Copy link
Member Author

Choose a reason for hiding this comment

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

I agree, that's a much better change. I missed that ShowExceptions sets action_dispatch.original_request_method which is what was needed to make that work!

@skipkayhil skipkayhil force-pushed the hm-lint-head-body branch from 4659801 to e006dac Compare June 4, 2025 17:25
@skipkayhil skipkayhil changed the title Fix {Show,Debug}Exceptions rendering body for HEAD Fix {Public,Debug}Exceptions rendering body for HEAD Jun 4, 2025
@Edouard-chin
Copy link
Member

👍 !

(You can rebase from main if you want CI to be green)

Rack::Lint already errors in this case, it just wasn't being covered.

```
Error:
DebugExceptionsTest#test_returns_empty_body_on_HEAD_cascade_pass:
Rack::Lint::LintError: Response body was given for HEAD request, but should be empty
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-3.1.15/lib/rack/lint.rb:773:in 'Rack::Lint::Wrapper#verify_content_length'
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-3.1.15/lib/rack/lint.rb:899:in 'Rack::Lint::Wrapper#each'
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-3.1.15/lib/rack/response.rb:345:in 'Rack::Response::Helpers#buffered_body!'
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-3.1.15/lib/rack/mock_response.rb:65:in 'Rack::MockResponse#initialize'
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-test-2.2.0/lib/rack/test.rb:362:in 'Class#new'
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-test-2.2.0/lib/rack/test.rb:362:in 'Rack::Test::Session#process_request'
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-test-2.2.0/lib/rack/test.rb:153:in 'Rack::Test::Session#request'
    lib/action_dispatch/testing/integration.rb:297:in 'ActionDispatch::Integration::Session#process'
    lib/action_dispatch/testing/integration.rb:49:in 'ActionDispatch::Integration::RequestHelpers#head'
    lib/action_dispatch/testing/integration.rb:388:in 'ActionDispatch::Integration::Runner#head'
    test/dispatch/debug_exceptions_test.rb:189:in 'block in <class:DebugExceptionsTest>'

Error:
ShowExceptionsTest#test_rescue_with_no_body_for_HEAD_requests:
Rack::Lint::LintError: Response body was given for HEAD request, but should be empty
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-3.1.15/lib/rack/lint.rb:773:in 'Rack::Lint::Wrapper#verify_content_length'
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-3.1.15/lib/rack/lint.rb:900:in 'Rack::Lint::Wrapper#each'
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-3.1.15/lib/rack/response.rb:345:in 'Rack::Response::Helpers#buffered_body!'
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-3.1.15/lib/rack/mock_response.rb:65:in 'Rack::MockResponse#initialize'
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-test-2.2.0/lib/rack/test.rb:362:in 'Class#new'
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-test-2.2.0/lib/rack/test.rb:362:in 'Rack::Test::Session#process_request'
    /home/hartley/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rack-test-2.2.0/lib/rack/test.rb:153:in 'Rack::Test::Session#request'
    lib/action_dispatch/testing/integration.rb:297:in 'ActionDispatch::Integration::Session#process'
    lib/action_dispatch/testing/integration.rb:49:in 'ActionDispatch::Integration::RequestHelpers#head'
    lib/action_dispatch/testing/integration.rb:388:in 'ActionDispatch::Integration::Runner#head'
    test/dispatch/show_exceptions_test.rb:73:in 'block in <class:ShowExceptionsTest>'
```
@skipkayhil skipkayhil force-pushed the hm-lint-head-body branch from e006dac to dce59e8 Compare June 4, 2025 19:43
@@ -28,7 +28,11 @@ def call(env)
content_type = request.formats.first
body = { status: status, error: Rack::Utils::HTTP_STATUS_CODES.fetch(status, Rack::Utils::HTTP_STATUS_CODES[500]) }

render(status, content_type, body)
if env["action_dispatch.original_request_method"] == "HEAD"
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if env["action_dispatch.original_request_method"] == "HEAD"
if request.raw_request_method == "HEAD

Not a huge deal, but since we instantiated a request, we could use the slightly nicer API.

Copy link
Member

Choose a reason for hiding this comment

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

Nevermind, Running your tests I see why you used that now. It's to avoid method rewrites.

@byroot byroot merged commit 4b7fb1d into rails:main Jun 5, 2025
3 checks passed
skipkayhil added a commit to skipkayhil/rails that referenced this pull request Jun 5, 2025
Fix {Public,Debug}Exceptions rendering body for HEAD

Co-authored-by: Hartley McGuire <skipkayhil@gmail.com>
skipkayhil added a commit to skipkayhil/rails that referenced this pull request Jun 5, 2025
Fix {Public,Debug}Exceptions rendering body for HEAD

Co-authored-by: Hartley McGuire <skipkayhil@gmail.com>
eileencodes added a commit that referenced this pull request Jun 9, 2025
eileencodes added a commit that referenced this pull request Jun 9, 2025
@skipkayhil skipkayhil deleted the hm-lint-head-body branch June 9, 2025 15:46
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.

Response body was given for HEAD request, but should be empty (Rack::Lint::LintError) after upgrading to rails 7.1 from 7.0
3 participants