From 9dd464a72b9981b1ec5efae5ed04821995639ca9 Mon Sep 17 00:00:00 2001 From: Jan Kneschke Date: Wed, 31 Aug 2005 13:39:09 +0000 Subject: [PATCH] moved last-modifed handling to response.c and let mod_cml_lua.c use it. git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-merge-1.4.x@655 152afb58-edef-0310-8abb-c4023f1b3aa9 --- src/mod_cml_lua.c | 22 +++++++++-- src/mod_staticfile.c | 84 ++-------------------------------------- src/response.c | 91 ++++++++++++++++++++++++++++++++++++++++++++ src/response.h | 2 +- 4 files changed, 113 insertions(+), 86 deletions(-) diff --git a/src/mod_cml_lua.c b/src/mod_cml_lua.c index 7b5b4586..fe6cbeff 100644 --- a/src/mod_cml_lua.c +++ b/src/mod_cml_lua.c @@ -322,18 +322,32 @@ int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn) { lua_settop(L, curelem - 1); if (ret == 0) { + data_string *ds; + char timebuf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")]; + buffer tbuf; + con->file_finished = 1; - + + ds = (data_string *)array_get_element(con->response.headers, "Last-Modified"); + /* no Last-Modified specified */ - if (mtime && NULL == array_get_element(con->response.headers, "Last-Modified")) { - char timebuf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")]; + if ((mtime) && (NULL == ds)) { strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&mtime)); response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), timebuf, sizeof(timebuf) - 1); + + + tbuf.ptr = timebuf; + tbuf.used = sizeof(timebuf); + tbuf.size = sizeof(timebuf); + } else if (ds) { + tbuf.ptr = ds->value->ptr; + tbuf.used = ds->value->used; + tbuf.size = ds->value->size; } - if (http_response_handle_cachable(srv, con, mtime)) { + if (http_response_handle_cachable(srv, con, &tbuf)) { /* ok, the client already has our content, * no need to send it again */ chunkqueue_reset(con->write_queue); diff --git a/src/mod_staticfile.c b/src/mod_staticfile.c index 0fe9fa83..122fb0aa 100644 --- a/src/mod_staticfile.c +++ b/src/mod_staticfile.c @@ -445,87 +445,9 @@ URIHANDLER_FUNC(mod_staticfile_subrequest) { } else { mtime = ds->value; } - - /* - * 14.26 If-None-Match - * [...] - * If none of the entity tags match, then the server MAY perform the - * requested method as if the If-None-Match header field did not exist, - * but MUST also ignore any If-Modified-Since header field(s) in the - * request. That is, if no entity tags match, then the server MUST NOT - * return a 304 (Not Modified) response. - */ - - /* last-modified handling */ - if (con->request.http_if_none_match) { - if (etag_is_equal(con->physical.etag, con->request.http_if_none_match)) { - 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)) { - con->http_status = 304; - return HANDLER_FINISHED; - } else { - char buf[64]; - - /* convert to timestamp */ - if (used_len < sizeof(buf) - 1) { - time_t t; - struct tm tm; - - strncpy(buf, con->request.http_if_modified_since, used_len); - buf[used_len] = '\0'; - - strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm); - - if (-1 != (t = mktime(&tm)) && - t <= sce->st.st_mtime) { - con->http_status = 304; - return HANDLER_FINISHED; - } - } else { - log_error_write(srv, __FILE__, __LINE__, "ss", - con->request.http_if_modified_since, buf); - - con->http_status = 412; - return HANDLER_FINISHED; - } - } - } else { - con->http_status = 304; - return HANDLER_FINISHED; - } - } else { - con->http_status = 412; - return HANDLER_FINISHED; - } - } - } else 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)) { - con->http_status = 304; - return HANDLER_FINISHED; - } + + if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, mtime)) { + return HANDLER_FINISHED; } else if (con->request.http_range) { /* content prepared, I'm done */ con->file_finished = 1; diff --git a/src/response.c b/src/response.c index 33a3c1a6..30d15bd3 100644 --- a/src/response.c +++ b/src/response.c @@ -550,3 +550,94 @@ handler_t http_response_prepare(server *srv, connection *con) { /* can't happen */ return HANDLER_COMEBACK; } + + + +int http_response_handle_cachable(server *srv, connection *con, buffer *mtime) { + /* + * 14.26 If-None-Match + * [...] + * If none of the entity tags match, then the server MAY perform the + * requested method as if the If-None-Match header field did not exist, + * but MUST also ignore any If-Modified-Since header field(s) in the + * request. That is, if no entity tags match, then the server MUST NOT + * return a 304 (Not Modified) response. + */ + + /* last-modified handling */ + if (con->request.http_if_none_match) { + if (etag_is_equal(con->physical.etag, con->request.http_if_none_match)) { + 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)) { + con->http_status = 304; + return HANDLER_FINISHED; + } else { + char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")]; + + /* convert to timestamp */ + if (used_len < sizeof(buf) - 1) { + time_t t_header, t_file; + struct tm tm; + + strncpy(buf, con->request.http_if_modified_since, used_len); + buf[used_len] = '\0'; + + strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm); + t_header = mktime(&tm); + + strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm); + t_file = mktime(&tm); + + if (t_file > t_header) { + con->http_status = 304; + return HANDLER_FINISHED; + } + } else { + log_error_write(srv, __FILE__, __LINE__, "ss", + con->request.http_if_modified_since, buf); + + con->http_status = 412; + return HANDLER_FINISHED; + } + } + } else { + con->http_status = 304; + return HANDLER_FINISHED; + } + } else { + con->http_status = 412; + return HANDLER_FINISHED; + } + } + } else 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)) { + con->http_status = 304; + return HANDLER_FINISHED; + } + } + + return HANDLER_GO_ON; +} diff --git a/src/response.h b/src/response.h index 4ff96a90..c9ff2344 100644 --- a/src/response.h +++ b/src/response.h @@ -13,7 +13,7 @@ int response_header_overwrite(server *srv, connection *con, const char *key, siz handler_t http_response_prepare(server *srv, connection *con); int http_response_redirect_to_directory(server *srv, connection *con); -int http_response_handle_cachable(server *srv, connection *con, time_t mtime); +int http_response_handle_cachable(server *srv, connection *con, buffer * mtime); buffer * strftime_cache_get(server *srv, time_t last_mod); #endif