Page MenuHomePhabricator

Incorrect handling of ETags taking precedence over timestamps in conditional requests
Open, Needs TriagePublicBUG REPORT

Description

During our work on the Wikibase REST API, we found that MediaWiki's Apache incorrectly handles conditional requests, when both If-None-Matchand If-Modified-Since headers are provided:

$ curl -i --request GET \
  --url http://default.mediawiki.mwdd.localhost:8080/w/rest2.php/wikibase/v0/entities/items/Q11 \
  --header 'If-Modified-Since: Wed, 28 Sep 2022 14:40:20 GMT' \
  --header 'If-None-Match: "999"'

HTTP/1.1 200 OK
Server: nginx/1.21.5
Date: Fri, 07 Oct 2022 11:52:23 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 0
Connection: keep-alive
X-Xdebug-Profile-Filename: /tmp/cachegrind.out.17
Upgrade: h2
ETag: "999"
Last-Modified: Wed, 28 Sep 2022 14:40:21 GMT

The server returns 200, because the If-Modified-Since condition is met. However, the If-None-Match condition is not met and according to Section 13.1.3. of RFC 9110

A recipient MUST ignore If-Modified-Since if the request contains an If-None-Match header field;

Thus, the expected HTTP status code is 304 Not Modified.

Similarly, MediaWiki's Apache incorrectly handles conditional requests, when both If-Match and If-Unmodified-Since headers are provided:

$ curl -i --request GET \
  --url http://default.mediawiki.mwdd.localhost:8080/w/rest2.php/wikibase/v0/entities/items/Q11 \
  --header 'If-Match: "999"' \
  --header 'If-Unmodified-Since: Wed, 28 Sep 2022 14:40:20 GMT'

HTTP/1.1 412 Precondition Failed
Server: nginx/1.21.5
Date: Fri, 07 Oct 2022 11:53:44 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 0
Connection: keep-alive
X-Xdebug-Profile-Filename: /tmp/cachegrind.out.12
Upgrade: h2
ETag: "999"
Last-Modified: Wed, 28 Sep 2022 14:40:21 GMT

The server returns 412, because the If-Unmodified-Since condition is not met. However, the If-Match condition is met and according to Section 13.1.4. of RFC 9110

A recipient MUST ignore If-Unmodified-Since if the request contains an If-Match header field;

Thus, the expected HTTP status code is 200 OK.