Use expected casing for x-cascade headers in router

This commit changes the router to use the expected casing for the
x-cascade header: in Rack 2, this is mixed-case, and in Rack 3, this is
lower case.

This also fixes https://github.com/rails/rails/issues/47096.
This commit is contained in:
Adrianna Chang 2023-07-28 15:38:43 -04:00
parent 596c2a0dc4
commit 2401b336fb
No known key found for this signature in database
GPG Key ID: 6816AFC60CB96DE5
13 changed files with 28 additions and 25 deletions

@ -13,6 +13,7 @@ module Constants
LOCATION = "Location"
FEATURE_POLICY = "Feature-Policy"
X_REQUEST_ID = "X-Request-Id"
X_CASCADE = "X-Cascade"
SERVER_TIMING = "Server-Timing"
STRICT_TRANSPORT_SECURITY = "Strict-Transport-Security"
else
@ -23,6 +24,7 @@ module Constants
LOCATION = "location"
FEATURE_POLICY = "feature-policy"
X_REQUEST_ID = "x-request-id"
X_CASCADE = "x-cascade"
SERVER_TIMING = "server-timing"
STRICT_TRANSPORT_SECURITY = "strict-transport-security"
end

@ -72,7 +72,7 @@ def commit_cookie_jar! # :nodoc:
PASS_NOT_FOUND = Class.new { # :nodoc:
def self.action(_); self; end
def self.call(_); [404, { "X-Cascade" => "pass" }, []]; end
def self.call(_); [404, { Constants::X_CASCADE => "pass" }, []]; end
def self.action_encoding_template(action); false; end
}

@ -50,7 +50,7 @@ def serve(req)
_, headers, _ = response = route.app.serve(req)
if "pass" == headers["X-Cascade"]
if "pass" == headers[Constants::X_CASCADE]
req.script_name = script_name
req.path_info = path_info
req.path_parameters = set_params
@ -60,7 +60,7 @@ def serve(req)
return response
end
[404, { "X-Cascade" => "pass" }, ["Not Found"]]
[404, { Constants::X_CASCADE => "pass" }, ["Not Found"]]
end
def recognize(rails_req)

@ -28,7 +28,7 @@ def initialize(app, routes_app = nil, response_format = :default, interceptors =
def call(env)
_, headers, body = response = @app.call(env)
if headers["X-Cascade"] == "pass"
if headers[Constants::X_CASCADE] == "pass"
body.close if body.respond_to?(:close)
raise ActionController::RoutingError, "No route matches [#{env['REQUEST_METHOD']}] #{env['PATH_INFO'].inspect}"
end

@ -55,7 +55,7 @@ def render_html(status)
if found || File.exist?(path)
render_format(status, "text/html", File.read(path))
else
[404, { "X-Cascade" => "pass" }, []]
[404, { Constants::X_CASCADE => "pass" }, []]
end
end
end

@ -50,7 +50,7 @@ def render_exception(request, wrapper)
request.path_info = "/#{status}"
request.request_method = "GET"
response = @exceptions_app.call(request.env)
response[1]["X-Cascade"] == "pass" ? pass_response(status) : response
response[1][Constants::X_CASCADE] == "pass" ? pass_response(status) : response
rescue Exception => failsafe_error
$stderr.puts "Error during failsafe response: #{failsafe_error}\n #{failsafe_error.backtrace * "\n "}"

@ -46,7 +46,7 @@ def matches?(req)
end
def serve(req)
return [ 404, { "X-Cascade" => "pass" }, [] ] unless matches?(req)
return [ 404, { Constants::X_CASCADE => "pass" }, [] ] unless matches?(req)
@strategy.call @app, req
end

@ -34,7 +34,7 @@ def serve(req)
if @raise_on_name_error
raise
else
[404, { "X-Cascade" => "pass" }, []]
[404, { Constants::X_CASCADE => "pass" }, []]
end
end

@ -782,7 +782,8 @@ def self.call(*)
get "bar", to: "application_integration_test/test#index", as: :bar
mount MountedApp => "/mounted", :as => "mounted"
get "fooz" => proc { |env| [ 200, { "X-Cascade" => "pass" }, [ "omg" ] ] }, :anchor => false
get "fooz" => proc { |env| [ 200, { ActionDispatch::Constants::X_CASCADE => "pass" }, [ "omg" ] ] },
:anchor => false
get "fooz", to: "application_integration_test/test#index"
end

@ -61,7 +61,7 @@ def call(env)
case req.path
when "/pass"
[404, { "X-Cascade" => "pass" }, self]
[404, { ActionDispatch::Constants::X_CASCADE => "pass" }, self]
when "/not_found"
controller = SimpleController.new
raise AbstractController::ActionNotFound.new(nil, controller, :ello)

@ -430,19 +430,19 @@ def test_admin
assert_equal "queenbee#index", @response.body
get "/admin", headers: { "REMOTE_ADDR" => "10.0.0.100" }
assert_equal "pass", @response.headers["X-Cascade"]
assert_equal "pass", @response.headers["x-cascade"]
get "/admin/accounts", headers: { "REMOTE_ADDR" => "192.168.1.100" }
assert_equal "queenbee#accounts", @response.body
get "/admin/accounts", headers: { "REMOTE_ADDR" => "10.0.0.100" }
assert_equal "pass", @response.headers["X-Cascade"]
assert_equal "pass", @response.headers["x-cascade"]
get "/admin/passwords", headers: { "REMOTE_ADDR" => "192.168.1.100" }
assert_equal "queenbee#passwords", @response.body
get "/admin/passwords", headers: { "REMOTE_ADDR" => "10.0.0.100" }
assert_equal "pass", @response.headers["X-Cascade"]
assert_equal "pass", @response.headers["x-cascade"]
end
def test_global
@ -890,13 +890,13 @@ def test_resource_routes_with_only_and_except
assert_equal "/posts/1/comments", post_comments_path(post_id: 1)
post "/posts"
assert_equal "pass", @response.headers["X-Cascade"]
assert_equal "pass", @response.headers["x-cascade"]
put "/posts/1"
assert_equal "pass", @response.headers["X-Cascade"]
assert_equal "pass", @response.headers["x-cascade"]
delete "/posts/1"
assert_equal "pass", @response.headers["X-Cascade"]
assert_equal "pass", @response.headers["x-cascade"]
delete "/posts/1/comments"
assert_equal "pass", @response.headers["X-Cascade"]
assert_equal "pass", @response.headers["x-cascade"]
end
def test_resource_routes_only_create_update_destroy
@ -1325,7 +1325,7 @@ def test_articles_with_id
assert_equal "articles#with_id", @response.body
get "/articles/123/1"
assert_equal "pass", @response.headers["X-Cascade"]
assert_equal "pass", @response.headers["x-cascade"]
assert_equal "/articles/rails/1", article_with_title_path(title: "rails", id: 1)
end
@ -1909,7 +1909,7 @@ def test_resource_constraints
end
get "/products/1"
assert_equal "pass", @response.headers["X-Cascade"]
assert_equal "pass", @response.headers["x-cascade"]
get "/products"
assert_equal "products#root", @response.body
get "/products/favorite"
@ -1918,14 +1918,14 @@ def test_resource_constraints
assert_equal "products#show", @response.body
get "/products/1/images"
assert_equal "pass", @response.headers["X-Cascade"]
assert_equal "pass", @response.headers["x-cascade"]
get "/products/0001/images"
assert_equal "images#index", @response.body
get "/products/0001/images/0001"
assert_equal "images#show", @response.body
get "/dashboard", headers: { "REMOTE_ADDR" => "10.0.0.100" }
assert_equal "pass", @response.headers["X-Cascade"]
assert_equal "pass", @response.headers["x-cascade"]
get "/dashboard", headers: { "REMOTE_ADDR" => "192.168.1.100" }
assert_equal "dashboards#show", @response.body
end

@ -117,9 +117,9 @@ def call(env)
assert_equal "YOU FAILED", body
end
test "returns an empty response if custom exceptions app returns X-Cascade pass" do
test "returns an empty response if custom exceptions app returns x-cascade pass" do
exceptions_app = lambda do |env|
[404, { "X-Cascade" => "pass" }, []]
[404, { ActionDispatch::Constants::X_CASCADE => "pass" }, []]
end
@app = ActionDispatch::ShowExceptions.new(Boomer.new, exceptions_app)

@ -110,11 +110,11 @@ def test_does_not_include_missing_keys_message
assert_no_match(/missing required keys: \[\]/, error.message)
end
def test_X_Cascade
def test_x_cascade
get "/messages(.:format)", to: "foo#bar"
resp = router.serve(rails_env("REQUEST_METHOD" => "GET", "PATH_INFO" => "/lol"))
assert_equal ["Not Found"], resp.last
assert_equal "pass", resp[1]["X-Cascade"]
assert_equal "pass", resp[1][Constants::X_CASCADE]
assert_equal 404, resp.first
end