Opened 8 years ago

Closed 8 years ago

Last modified 8 years ago

#27083 closed Bug (fixed)

Parse conditional HTTP headers according to RFC 7232

Reported by: Kevin Christopher Henry Owned by: Kevin Christopher Henry
Component: HTTP handling Version: dev
Severity: Normal Keywords:
Cc: k@… Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


There are a number of problems with the way Django currently parses and compares ETags. The main issue is that we don't properly distinguish between weak and strong ETags. Specifically:

  • Since we don't distinguish between weak and strong ETags, all of our comparisons are implicitly weak (see section 2.3.2 of RFC 7232). The specification, however, says that we "MUST use the strong comparison function when comparing entity-tags for If-Match" (section 3.1).
  • There's no way to supply a weak ETag via the condition() decorator.
  • If the developer specifies a weak ETag directly (by assigning to the ETag header in the response), we don't parse it properly and it will never match.
  • We interpret the ETag format and implement the matching algorithm based on the old specification (RFC 2616), not the new one (RFC 7232). They are somewhat different.

Correcting this is mostly straightforward. The only tricky issue is what to do about the ETags returned from etag_func() in the condition() decorator. We currently treat these as unquoted (and implicitly strong) ETags. We can't suddenly require these to be quoted ETags since that would break backwards compatibility.

Instead we can allow either quoted or unquoted ETags to be returned. Since quotes are not an allowed character in the unquoted part of the ETag under the new specification, there won't be any ambiguity. Existing code will work as before, but it will now be possible for someone to provide an etag_func() that returns a weak ETag.

There is still the possibility of a backwards incompatibility, though, since as noted above the current ETag specification is slightly incompatible with the old one (having to do with changing from an escaped string to an opaque string). That is, there exist ETags that would have been valid and would have matched under the old specification that will not match after this change. I would expect actual use of such ETags to be rare or nonexistent, and since the problem would be caused by user code that is incompatible with the HTTP specification this doesn't seem like a fatal problem.

Change History (8)

comment:1 by Kevin Christopher Henry, 8 years ago

Cc: k@… added
Has patch: set
Needs documentation: set
Needs tests: set
Owner: changed from nobody to Kevin Christopher Henry
Patch needs improvement: set
Status: newassigned

comment:2 by Tim Graham, 8 years ago

Triage Stage: UnreviewedAccepted

comment:3 by Kevin Christopher Henry, 8 years ago

Needs documentation: unset
Needs tests: unset
Patch needs improvement: unset

comment:4 by Tim Graham, 8 years ago

Patch needs improvement: set
Summary: Problems with ETag parsing and comparisonAdd support for weak ETags

I left some comments for improvement.

comment:5 by Kevin Christopher Henry, 8 years ago

Patch needs improvement: unset

comment:6 by Tim Graham <timograham@…>, 8 years ago

Resolution: fixed
Status: assignedclosed

In 4ef0e019:

Fixed #27083 -- Added support for weak ETags.

comment:7 by Kevin Christopher Henry, 8 years ago

Summary: Add support for weak ETagsParse conditional HTTP headers according to RFC 7232

comment:8 by Tim Graham <timograham@…>, 8 years ago

In 22e3038:

Refs #27083 -- Updated conditional header comparison to match RFC 7232.

Note: See TracTickets for help on using tickets.
Back to Top