Skip to content

assets: match If-None-Match lists and "*", and skip If-Modified-Since when If-None-Match is present - #4027

Merged
jknack merged 1 commit into
jooby-project:mainfrom
wleeaf:asset-conditional-requests
Oct 26, 2026
Merged

jknack merged 1 commit into
jooby-project:mainfrom
wleeaf:asset-conditional-requests

Conversation

@wleeaf

@wleeaf wleeaf commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

AssetHandler handles conditional requests in three ways that differ from RFC 9110.

  1. If-None-Match is compared as one string. The field is * or a comma-separated list of entity tags, compared with the weak comparison function, so W/"x" and "x" match (section 13.1.2). Today these requests get a full 200 for an unchanged asset:
    • If-None-Match: "x", W/"<etag>"
    • If-None-Match: *
    • If-None-Match: "<etag>", the ETag without W/
  2. If-Modified-Since is checked even when If-None-Match is present. Section 13.2.2 says it is only evaluated when the request has no If-None-Match. As a result, If-None-Match: "stale" together with the asset's own Last-Modified gets 304, and a cache keeps a response whose ETag the server no longer has. ETags are more precise than dates (one-second resolution), which is why they take precedence.
  3. An If-Modified-Since that isn't a date is a 400. If-Modified-Since: yesterday throws TypeMismatchException from Value.longValue. Section 13.1.3 says the recipient must ignore a value that isn't a valid HTTP-date.

The change:

  • Matches If-None-Match with a new etagMatches(): an exact match as before, or *, or a list element equal to the ETag once W/ is removed from both.
  • Reads If-Modified-Since only when the request has no If-None-Match.
  • Treats an unparseable If-Modified-Since as absent.

A 304 still has no ETag, as FeaturedTest expects.

The new AssetHandlerTest (Mockito, like the other handler tests) runs nine header combinations against a mocked Asset. Without the change, six of them fail: the strong form, both lists and * get 200, the stale tag plus date gets 304, and yesterday throws. mvn -pl jooby test passes (1307 tests), and spotless:check reports no violations in the changed files.

@codecov

codecov Bot commented Oct 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.19%. Comparing base (e64c771) to head (85238dc).

Additional details and impacted files
@@            Coverage Diff            @@
##               main    #4027   +/-   ##
=========================================
  Coverage     94.18%   94.19%           
- Complexity     6656     6665    +9     
=========================================
  Files           432      432           
  Lines         20897    20909   +12     
  Branches       2096     2099    +3     
=========================================
+ Hits          19682    19695   +13     
+ Misses          762      759    -3     
- Partials        453      455    +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jknack jknack added this to the 4.5.5 milestone Oct 26, 2026
@jknack
jknack merged commit 7e01589 into jooby-project:main Oct 26, 2026
6 checks passed
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.

2 participants