fix handling of If-Modified-Since if If-None-Match is present (don't return 412 for date parsing errors); follow current draft for HTTP/1.1, which tells us to ignore If-Modified-Since if we have matching etags.
See: http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-21#section-5 > it makes sense to ignore the If-Modified-Since when entity tags are > understood and available for the selected representation. git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@2865 152afb58-edef-0310-8abb-c4023f1b3aa9
This commit is contained in:
parent
9cd8faa1b6
commit
543bd249fb
2
NEWS
2
NEWS
|
@ -5,6 +5,8 @@ NEWS
|
|||
|
||||
- 1.4.33 -
|
||||
* mod_fastcgi: fix mix up of "mode" => "authorizer" in other fastcgi configs (fixes #2465, thx peex)
|
||||
* fix handling of If-Modified-Since if If-None-Match is present (don't return 412 for date parsing errors);
|
||||
follow current draft for HTTP/1.1, which tells us to ignore If-Modified-Since if we have matching etags.
|
||||
|
||||
- 1.4.32 - 2012-11-21
|
||||
* Code cleanup with clang/sparse (fixes #2437, thx kibi)
|
||||
|
|
|
@ -245,6 +245,7 @@ buffer * strftime_cache_get(server *srv, time_t last_mod) {
|
|||
|
||||
|
||||
int http_response_handle_cachable(server *srv, connection *con, buffer *mtime) {
|
||||
UNUSED(srv);
|
||||
/*
|
||||
* 14.26 If-None-Match
|
||||
* [...]
|
||||
|
@ -261,68 +262,17 @@ int http_response_handle_cachable(server *srv, connection *con, buffer *mtime) {
|
|||
if (con->request.http_method == HTTP_METHOD_GET ||
|
||||
con->request.http_method == HTTP_METHOD_HEAD) {
|
||||
|
||||
/* check if etag + last-modified */
|
||||
if (con->request.http_if_modified_since) {
|
||||
size_t used_len;
|
||||
char *semicolon;
|
||||
|
||||
if (NULL == (semicolon = strchr(con->request.http_if_modified_since, ';'))) {
|
||||
used_len = strlen(con->request.http_if_modified_since);
|
||||
} else {
|
||||
used_len = semicolon - con->request.http_if_modified_since;
|
||||
}
|
||||
|
||||
if (0 == strncmp(con->request.http_if_modified_since, mtime->ptr, used_len)) {
|
||||
if ('\0' == mtime->ptr[used_len]) con->http_status = 304;
|
||||
return HANDLER_FINISHED;
|
||||
} else {
|
||||
char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
|
||||
time_t t_header, t_file;
|
||||
struct tm tm;
|
||||
|
||||
/* check if we can safely copy the string */
|
||||
if (used_len >= sizeof(buf)) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "ssdd",
|
||||
"DEBUG: Last-Modified check failed as the received timestamp was too long:",
|
||||
con->request.http_if_modified_since, used_len, sizeof(buf) - 1);
|
||||
|
||||
con->http_status = 412;
|
||||
con->mode = DIRECT;
|
||||
return HANDLER_FINISHED;
|
||||
}
|
||||
|
||||
|
||||
strncpy(buf, con->request.http_if_modified_since, used_len);
|
||||
buf[used_len] = '\0';
|
||||
|
||||
if (NULL == strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm)) {
|
||||
con->http_status = 412;
|
||||
con->mode = DIRECT;
|
||||
return HANDLER_FINISHED;
|
||||
}
|
||||
tm.tm_isdst = 0;
|
||||
t_header = mktime(&tm);
|
||||
|
||||
strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
|
||||
tm.tm_isdst = 0;
|
||||
t_file = mktime(&tm);
|
||||
|
||||
if (t_file > t_header) return HANDLER_GO_ON;
|
||||
|
||||
con->http_status = 304;
|
||||
return HANDLER_FINISHED;
|
||||
}
|
||||
} else {
|
||||
con->http_status = 304;
|
||||
return HANDLER_FINISHED;
|
||||
}
|
||||
con->http_status = 304;
|
||||
return HANDLER_FINISHED;
|
||||
} else {
|
||||
con->http_status = 412;
|
||||
con->mode = DIRECT;
|
||||
return HANDLER_FINISHED;
|
||||
}
|
||||
}
|
||||
} else if (con->request.http_if_modified_since) {
|
||||
} else if (con->request.http_if_modified_since &&
|
||||
(con->request.http_method == HTTP_METHOD_GET ||
|
||||
con->request.http_method == HTTP_METHOD_HEAD)) {
|
||||
size_t used_len;
|
||||
char *semicolon;
|
||||
|
||||
|
|
|
@ -78,8 +78,8 @@ If-None-Match: $etag
|
|||
If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
|
||||
EOF
|
||||
);
|
||||
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
|
||||
ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + old Last-Modified');
|
||||
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
|
||||
ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + old Last-Modified (which should be ignored)');
|
||||
|
||||
$t->{REQUEST} = ( <<EOF
|
||||
GET / HTTP/1.0
|
||||
|
@ -88,7 +88,7 @@ If-Modified-Since: $now; foo
|
|||
EOF
|
||||
);
|
||||
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
|
||||
ok($tf->handle_http($t) == 0, 'Conditional GET - ETag, Last-Modified + comment');
|
||||
ok($tf->handle_http($t) == 0, 'Conditional GET - ETag, Last-Modified + comment (which should be ignored)');
|
||||
|
||||
$t->{REQUEST} = ( <<EOF
|
||||
GET / HTTP/1.0
|
||||
|
@ -105,8 +105,8 @@ If-None-Match: $etag
|
|||
If-Modified-Since: $now foo
|
||||
EOF
|
||||
);
|
||||
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 412 } ];
|
||||
ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + Last-Modified + overlong timestamp');
|
||||
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
|
||||
ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + Last-Modified + overlong timestamp (which should be ignored)');
|
||||
|
||||
$t->{REQUEST} = ( <<EOF
|
||||
GET / HTTP/1.0
|
||||
|
|
Loading…
Reference in New Issue