Skip auto-inserting Rack::Lint on Rack 3+#183
Open
dduugg wants to merge 1 commit into
Open
Conversation
Pitchfork's default app builder injects Rack::Lint into the middleware
stack whenever RACK_ENV is "development" (which exe/pitchfork sets via
ENV["RACK_ENV"] ||= "development" if unset). On Rack 3, the strict
Rack::Lint::Wrapper::InputWrapper no longer exposes rewind, but Rails
middleware (cookies, body parsers) and most third-party Rack middleware
still call request.body.rewind unconditionally, so the moment a Rails
dev process switches from Puma to Pitchfork every cookie- or
body-bearing request 500s with
undefined method 'rewind' for an instance of
Rack::Lint::Wrapper::InputWrapper
The dev-affordance value of the auto-insert no longer outweighs the
trap on Rack 3+. Gate the insert on Rack::RELEASE < "3" so Rack 2 users
keep the existing behavior and Rack 3 users stop tripping over the
incompatibility. Adds an integration test using the existing
fails-rack-lint.ru fixture to lock the new behavior in.
Closes Shopify#177.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Pitchfork's default app builder injects
Rack::Lintinto the middleware stack wheneverRACK_ENV == "development":https://github.com/Shopify/pitchfork/blob/v0.18.2/lib/pitchfork.rb#L100
Combined with
exe/pitchfork:7'sENV["RACK_ENV"] ||= "development", this means every Pitchfork process that didn't explicitly setRACK_ENVends up withRack::Lintin its stack.On Rack 3,
Rack::Lint::Wrapper::InputWrapperno longer exposesrewind(it was dropped from the strict spec). Rails middleware and most third-party Rack middleware still callrequest.body.rewindunconditionally, so any Rails dev process that switches from Puma to Pitchfork starts 500ing on every cookie- or body-bearing request:This is #177 — the linked issue documents one observable failure (
request.raw_postreturns nil viaRack::MethodOverrideexhausting the stream, thenActionDispatch::Request#reset_streamcan't rewind). We hit it in a different shape:ActionDispatch::Cookiesand third-party analytics middleware callrewinddirectly withoutrespond_to?(:rewind)guards, so the failure happens before any controller runs, and the entire Rails GraphQL surface goes dark in dev.Fix
Gate the auto-insert on
Rack::RELEASE < "3". Rack 2 users keep the existing dev affordance. Rack 3 users stop tripping over the incompatibility.The integration test uses the existing
test/integration/fails-rack-lint.rufixture (which returns a response header thatRack::Lintwould 500 on). Withlint: true(the spawn_server default — RACK_ENV stays at the CLI's "development" default), the test asserts the response comes through unchanged on Rack 3+, which is only true if the gate keptRack::Lintout.Alternatives considered
Issue #177 surfaced three other options, none of which I picked:
ENV["RACK_ENV"] ||= "development"inexe/pitchfork. Cleanest from a Rails-convention standpoint (RAILS_ENV is the canonical source), but it's a behavior change for every Pitchfork user, not just Rack 3+ users, and it's load-bearing for the dev affordances on Rack 2.Rack::Lintwith a custom validator that delegatesrewindto the underlying input. More invasive, more code to maintain, and it leaks lint-spec violations of the rest of the spec we don't want to swallow.RACK_ENV=production(or equivalent) themselves. This is the workaround the issue lands on, but it's surprising — the trap fires the moment someone runsbin/pitchforkwithout reading the issue thread first.The Rack-version gate is the minimum change that removes the trap for the affected users without changing anything for the unaffected ones. Happy to take it in a different direction if you'd prefer one of the alternatives.
Notes
lint: false(which setsRACK_ENV=productionin the spawned process) are unaffected.test/integration/fails-rack-lint.ruis referenced only as a fixture; no test references it yet) is now covered by the new test — but only for the "Rack::Lint is not there" direction, which is what this PR introduces.