Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

### Fixed

- [API] Ignore `If-Modified-Since` when `If-None-Match` is present.
- [Request] Treat IPv6 literals as non-domain hosts.
- [Router] Fall back to `SERVER_NAME` when deriving exact host constraints.
- [Cookies] Use request host fallback when resolving cookie domains.
Expand Down
18 changes: 10 additions & 8 deletions lib/rage/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -169,16 +169,18 @@ def headers
# request.fresh?(last_modified: Time.utc(2023, 12, 15))
# request.fresh?(etag: "123")
def fresh?(etag:, last_modified:)
request_if_none_match = if_none_match
request_not_modified_since = if_not_modified_since

# Always render response when no freshness information
# is provided in the request.
return false unless if_none_match || if_not_modified_since

etag_matches?(
requested_etags: if_none_match, response_etag: etag
) && not_modified?(
request_not_modified_since: if_not_modified_since,
response_last_modified: last_modified
)
return false unless request_if_none_match || request_not_modified_since

if request_if_none_match
etag_matches?(requested_etags: request_if_none_match, response_etag: etag)
else
not_modified?(request_not_modified_since: request_not_modified_since, response_last_modified: last_modified)
end
end

# Get the domain part of the request.
Expand Down
25 changes: 20 additions & 5 deletions spec/controller/api/conditional_get_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,21 @@ def last_modified_set_raises_error
end
end

context "and If-None-Match matches but If-Modified-Since is stale" do
let(:env) do
{
"HTTP_IF_MODIFIED_SINCE" => Time.utc(2023, 11, 15).httpdate,
"HTTP_IF_NONE_MATCH" => %(W/"#{Digest::SHA1.hexdigest("123")}")
}
end

it "returns NOT MODIFIED" do
expect(run_action(klass, :stale_last_modified_and_etag_test, env:)).to match(
[304, a_hash_including(Rage::Response::ETAG_HEADER => expected_etag, Rage::Response::LAST_MODIFIED_HEADER => expected_last_modified), []]
)
end
end

context "and request is stale" do
let(:env) do
{
Expand Down Expand Up @@ -299,17 +314,17 @@ def last_modified_set_raises_error
context "and last_modified is not set in the action" do
let(:env) do
{
"HTTP_IF_MODIFIED_SINCE" => Time.utc(2023, 12, 15).httpdate,
"HTTP_IF_NONE_MATCH" => "123"
"HTTP_IF_MODIFIED_SINCE" => Time.utc(2023, 11, 15).httpdate,
"HTTP_IF_NONE_MATCH" => %(W/"#{Digest::SHA1.hexdigest("123")}")
}
end

it "renders the requested resource" do
it "returns NOT MODIFIED" do
expect(run_action(klass, :stale_etag_test, env:)).to match(
[200, a_hash_including(
[304, a_hash_including(
Rage::Response::ETAG_HEADER => expected_etag,
Rage::Response::LAST_MODIFIED_HEADER => nil
), ["test_etag"]]
), []]
)
end
end
Expand Down