Repeated headers produce 400 Bad Request
I've filed a bug in the squid-cache bugzilla (http://www.squid-cache.org/bugs/show_bug.cgi?id=1677) that squid produces a duplicate "If-None-Match:" header in it's request, which seems to make lighttpd return a "400 Bad Request":
# telnet localhost 80 GET / HTTP/1.0 If-Modified-Since: Thu, 06 Jul 2006 09:57:57 GMT If-None-Match: "714413461" If-None-Match: "714413461" HTTP/1.0 400 Bad Request Connection: close Content-Type: text/html Content-Length: 349 Date: Wed, 12 Jul 2006 08:14:49 GMT Server: lighttpd/1.4.11
But - according to RFC 2616, the repeated "If-None-Match:" header is both legal and equivalent to
If-None-Match: "714413461", "714413461"
which, if used instead, works just fine.
(Excerpt from RFC 2616:
| 4.2 Message Headers [...] | Multiple message-header fields with the same field-name MAY be | present in a message if and only if the entire field-value for that | header field is defined as a comma-separated list [i.e., #(values)]. | It MUST be possible to combine the multiple header fields into one | "field-name: field-value" pair, without changing the semantics of the | message, by appending each subsequent field-value to the first, each | separated by a comma. The order in which header fields with the same | field-name are received is therefore significant to the | interpretation of the combined field value, and thus a proxy MUST NOT | change the order of these field values when a message is forwarded. | 14.26 If-None-Match [...] | If-None-Match = "If-None-Match" ":" ( "*" | 1#entity-tag )
So while squid shouldn't duplicate the header in the first place, lighttpd should not produce a 400 Bad Request in response...
(Yeah, it should also probably say "HTTP/1.1" in the request from squid (which they said they won't do before they're fully 1.1 compliant), but changing the request into a valid HTTP/1.1 request still produces a 400 response code...)
Updated by Anonymous almost 15 years ago
More bugs in If-None-Match processing. Looks like lighttpd reads If-None-Match as a string header and not a list header.
produces a 304
If-None-Match: "currentetag", "anotheretag"
produces a 200, where a 304 was expected..
Updated by stbuehler over 12 years ago
- Status changed from New to Fixed
- Resolution set to invalid
If-None-Match = "If-None-Match" ":" ( "*" | 1#entity-tag )
Only one etag is allowed, so '"currentetag", "anotheretag"' is read as one etag, which of course doesn't match.
The a,b intepretation doesn't match the etag syntax anyway; so 400 is the right answer. 1.5 worksaround this by killing a duplicate if it has the same etag.
Updated by Anonymous over 12 years ago
- Status changed from Fixed to Need Feedback
- Resolution deleted (
No, the initial reporter is right here.
Please read the definition of #rule in the BNF description again:
A construct "#" is defined, similar to "*", for defining lists of
elements. The full form is "<n>#<m>element" indicating at least
<n> and at most <m> elements, each separated by one or more commas
(",") and OPTIONAL linear white space (LWS). This makes the usual
form of lists very easy; a rule such as
( *LWS element *( *LWS "," *LWS element ))
can be shown as
Which means that 1#etag is a list of etags, with at least one member.
Also available in: Atom