Bug #753


Repeated headers produce 400 Bad Request

Added by Anonymous over 17 years ago. Updated over 14 years ago.

Target version:


I've filed a bug in the squid-cache bugzilla ( 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...)

-- Bugzilla-Briareos

Actions #1

Updated by Anonymous over 17 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.

If-None-Match: "currentetag"

produces a 304

If-None-Match: "currentetag", "anotheretag"

produces a 200, where a 304 was expected..

-- hno

Actions #2

Updated by stbuehler over 15 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.

Actions #3

Updated by Anonymous over 15 years ago

  • Status changed from Fixed to Need Feedback
  • Resolution deleted (invalid)

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.

-- hno

Actions #4

Updated by stbuehler over 15 years ago

Sry, you are right. (stupid "bnf" syntax...).

Actions #5

Updated by icy almost 15 years ago

  • Target version changed from 1.4.21 to 1.4.22
  • Patch available set to No
Actions #6

Updated by stbuehler almost 15 years ago

  • Target version changed from 1.4.22 to 1.4.23
Actions #7

Updated by stbuehler over 14 years ago

  • Status changed from Need Feedback to Fixed
  • % Done changed from 0 to 100

Applied in changeset r2528.


Also available in: Atom