Bug #2578


If-None-Match handling does not comply with RFC2616

Added by argonel about 10 years ago. Updated almost 9 years ago.

Target version:


In the case where a client knows there might be more than one ETag for a resource, it can supply all of the ETags it has and the server should return a 304 if one of them matches. A client could suppose that an ETag is weak and submit it as such, regardless of whether the server originally send a weak ETag.

Attached is a patch that adds full support for If-None-Match as defined in RFC2616.

This patch does not attempt to cause lighttpd to actually send weak ETags.


ifnonematch.patch (7.86 KB) ifnonematch.patch patch on lighttpd-1.4.35-2-g3605a3b argonel, 2014-04-17 23:38
Actions #1

Updated by stbuehler almost 10 years ago

  • % Done changed from 90 to 50

Hi. Thx for your work so far!

  • I wasn't completely happy with the parser and rewrote it a little bit
  • We usually use tabs to indent
  • "ISO C90 forbids mixed declarations and code" (http-header-glue.c)
  • As far as I understand the RFC weak ETag validation must not be used for ranged requests; I therefor had to disable the weak check. Also added a test case for it, and made the two weak cases "TODO" items.
  • I think the RFC accepts empty "tokens" - skipping "," in START should fix it, i.e. If-None-Match: ,"1", ,, "2"
  • Tokens must always be separated by at least one "," - TAIL must only go to START with a ","
  • I'm not completely sure whether the quoted pairs have to match - is "a" equal to "\a" or not? For now I assume they are not equal: "both validators MUST be identical in every way"

See for my current patch.

I can add your account name + email (or something else) as author if you want.

Any good ideas how to solve the weak ETag validation vs. ranged request thing? Is it really needed? Perhaps etag_is_equal could be extended to return whether it was a strong or a weak match, although I'd like a different function name for that.

Some notes what I changed - maybe you can use the feedback:
  • I think char is a bad substitute for bool - char is a "special" integral type. It certainly saves no memory on the stack, in registers or in function parameters. I used int instead.
  • Mixed returning of enum values and "boolean" values (!...) - this is wrong. The function names indicates the return value is a boolean, and therefore the returned values should only be 0 or 1 (or FALSE / TRUE).
  • Just directly return on success instead of using a special state (and !state is not very readably - enum values should be compared explicitly, so searching for them is easier)
  • enum { FOUND_TOKEN = 0, START, TOKEN, MAYBE_WEAK, QUOTING, TAIL } states; - unused variable states. Perhaps this was inteded as a typedef (typedef enum {...} states;)?
  • I like to do comparisions with constant values the other way round, so I don't accidentally assign stuff (if ('"' == *current) instead of if (*current == '"')); your const char* pointers would have prevented assignments too ofc.
  • We have case labels on the same indentation level as the surrounding switch - that way { and } add and remove always exactly one level.
Actions #2

Updated by stbuehler almost 9 years ago

  • Status changed from New to Fixed
  • % Done changed from 50 to 100

Applied in changeset r2994.


Also available in: Atom