Skip to content

Commit

Permalink
Deprecate automatic cache invalidation in Request#{GET,POST}
Browse files Browse the repository at this point in the history
Add Request#clear_{GET,POST} for users to perform manual cache
invalidation when replacing env['QUERY_STRING'] or env['rack.input'].

With this invalidation, env[RACK_REQUEST_QUERY_STRING] and
env[RACK_REQUEST_FORM_INPUT] are unnecessary.

It appears as though env[RACK_REQUEST_FORM_VARS] is already
unnecessary, as the value is set but never accessed, dating back to
its introduction in 6c80c6c.
However, even though it is never used by Rack, it apparently is
used by Rails.  However, Rails usage appears to be limited to
parameter filtering, and if the RACK_REQUEST_FORM_VARS key wasn't
set, there would be nothing to filter.  So it's possible Rails
could be changed so that if the key was missing, there are no
problems (maybe it works like that already, and only the Rails
tests need updates).
  • Loading branch information
jeremyevans committed Apr 25, 2023
1 parent ab360dd commit a5691a5
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ All notable changes to this project will be documented in this file. For info on
- MIME type for JavaScript files (`.js`) changed from `application/javascript` to `text/javascript` ([`1bd0f15`](https://github.com/rack/rack/commit/1bd0f1597d8f4a90d47115f3e156a8ce7870c9c8))
- Add `.mjs` MIME type ([#2057](https://github.com/rack/rack/pull/2057), [@axilleas])
- Update MIME types associated to `.ttf`, `.woff`, `.woff2` and `.otf` extensions to use mondern `font/*` types. ([#2065](https://github.com/rack/rack/pull/2065), [@davidstosik])
- Deprecate automatic cache invalidation in `Request#{GET,POST}` and add `Request#clear_{GET,POST}` for manual cache invalidation ([@jeremyevans])

## [3.0.7] - 2023-03-16

Expand Down
30 changes: 28 additions & 2 deletions lib/rack/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -480,11 +480,34 @@ def parseable_data?
PARSEABLE_DATA_MEDIA_TYPES.include?(media_type)
end

# Clear cached data related to GET/query string parameters.
# Should be called if modifying env["QUERY_STRING"].
def clear_GET
env.delete(RACK_REQUEST_QUERY_STRING) # Remove in Rack 3.2
env.delete(RACK_REQUEST_QUERY_HASH)
@params = nil
end

# Clear cached data related to POST/request body parameters.
# Should be called if modifying env["rack.input"].
def clear_POST
env.delete(RACK_REQUEST_FORM_INPUT) # Remove in Rack 3.2
env.delete(RACK_REQUEST_FORM_VARS)
env.delete(RACK_REQUEST_FORM_HASH)
env.delete(RACK_REQUEST_FORM_ERROR)
@params = nil
end

# Returns the data received in the query string.
def GET
if get_header(RACK_REQUEST_QUERY_STRING) == query_string
rr_query_string = get_header(RACK_REQUEST_QUERY_STRING)
query_string = self.query_string
if rr_query_string == query_string
get_header(RACK_REQUEST_QUERY_HASH)
else
if rr_query_string
warn "Cached query string different from current query string. Starting in Rack 3.2, you must call clear_GET when modifying env[\"QUERY_STRING\"]", uplevel: 1
end
query_hash = parse_query(query_string, '&')
set_header(RACK_REQUEST_QUERY_STRING, query_string)
set_header(RACK_REQUEST_QUERY_HASH, query_hash)
Expand All @@ -505,9 +528,12 @@ def POST

# If the form hash was already memoized:
if form_hash = get_header(RACK_REQUEST_FORM_HASH)
form_input = get_header(RACK_REQUEST_FORM_INPUT)
# And it was memoized from the same input:
if get_header(RACK_REQUEST_FORM_INPUT).equal?(rack_input)
if form_input.equal?(rack_input)
return form_hash
elsif form_input
warn "Cached input stream value different from current input stream. Starting in Rack 3.2, you must call clear_POST when modifying env[\"#{RACK_INPUT}\"]", uplevel: 1
end
end

Expand Down
25 changes: 24 additions & 1 deletion test/spec_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -911,7 +911,7 @@ def initialize(*)
req.media_type.must_be_nil
end

it "cache, but invalidates the cache" do
deprecated "cache, but invalidates the cache" do
req = make_request \
Rack::MockRequest.env_for("/?foo=quux",
"CONTENT_TYPE" => "application/x-www-form-urlencoded",
Expand All @@ -929,6 +929,29 @@ def initialize(*)
req.POST.must_equal "foo" => "bla", "quux" => "bar"
end

it "support manual cache invalidation via clear_GET and clear_POST" do
req = make_request \
Rack::MockRequest.env_for("/?foo=quux",
"CONTENT_TYPE" => "application/x-www-form-urlencoded",
:input => "foo=bar&quux=bla")
req.GET.must_equal "foo" => "quux"
req.GET.must_equal "foo" => "quux"
req.POST.must_equal "foo" => "bar", "quux" => "bla"
req.POST.must_equal "foo" => "bar", "quux" => "bla"

req.set_header("QUERY_STRING", "bla=foo")
req.clear_GET
req.GET.must_equal "bla" => "foo"
req.GET.must_equal "bla" => "foo"
req.params.must_equal "bla" => "foo", "foo" => "bar", "quux" => "bla"

req.set_header("rack.input", StringIO.new("foo=bla&quux=bar"))
req.clear_POST
req.POST.must_equal "foo" => "bla", "quux" => "bar"
req.POST.must_equal "foo" => "bla", "quux" => "bar"
req.params.must_equal "bla" => "foo", "foo" => "bla", "quux" => "bar"
end

it "figure out if called via XHR" do
req = make_request(Rack::MockRequest.env_for(""))
req.wont_be :xhr?
Expand Down

0 comments on commit a5691a5

Please sign in to comment.