From c3353ae565c3d3f9a605583b4c45abbdda7ac47b Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Thu, 8 Mar 2018 15:12:30 +1100 Subject: cpukit/mttpd: Add a callback to generate a per file HTTP etag. Closes #3324 --- cpukit/mghttpd/mongoose.c | 19 +++++++++++++------ cpukit/mghttpd/mongoose.h | 13 +++++++++++++ 2 files changed, 26 insertions(+), 6 deletions(-) (limited to 'cpukit') diff --git a/cpukit/mghttpd/mongoose.c b/cpukit/mghttpd/mongoose.c index dd243d3320..911ca64767 100644 --- a/cpukit/mghttpd/mongoose.c +++ b/cpukit/mghttpd/mongoose.c @@ -2989,10 +2989,16 @@ static void gmt_time_string(char *buf, size_t buf_len, time_t *t) { strftime(buf, buf_len, "%a, %d %b %Y %H:%M:%S GMT", gmtime(t)); } -static void construct_etag(char *buf, size_t buf_len, +static void construct_etag(const struct mg_connection *conn, const char *path, + char *buf, size_t buf_len, const struct file *filep) { - snprintf(buf, buf_len, "\"%lx.%" INT64_FMT "\"", - (unsigned long) filep->modification_time, filep->size); + if (conn->ctx->callbacks.http_etag != NULL && + conn->ctx->callbacks.http_etag(conn, path, buf, buf_len)) { + } + else { + snprintf(buf, buf_len, "\"%lx.%" INT64_FMT "\"", + (unsigned long) filep->modification_time, filep->size); + } } static void fclose_on_exec(struct file *filep) { @@ -3061,7 +3067,7 @@ static void handle_file_request(struct mg_connection *conn, const char *path, // http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3 gmt_time_string(date, sizeof(date), &curtime); gmt_time_string(lm, sizeof(lm), &filep->modification_time); - construct_etag(etag, sizeof(etag), filep); + construct_etag(conn, path, etag, sizeof(etag), filep); (void) mg_printf(conn, "HTTP/1.1 %d %s\r\n" @@ -3221,11 +3227,12 @@ static int substitute_index_file(struct mg_connection *conn, char *path, // Return True if we should reply 304 Not Modified. static int is_not_modified(const struct mg_connection *conn, + const char *path, const struct file *filep) { char etag[64]; const char *ims = mg_get_header(conn, "If-Modified-Since"); const char *inm = mg_get_header(conn, "If-None-Match"); - construct_etag(etag, sizeof(etag), filep); + construct_etag(conn, path, etag, sizeof(etag), filep); return (inm != NULL && !mg_strcasecmp(etag, inm)) || (ims != NULL && filep->modification_time <= parse_date_string(ims)); } @@ -4591,7 +4598,7 @@ static void handle_request(struct mg_connection *conn) { strlen(conn->ctx->config[SSI_EXTENSIONS]), path) > 0) { handle_ssi_file_request(conn, path); - } else if (is_not_modified(conn, &file)) { + } else if (is_not_modified(conn, path, &file)) { send_http_error(conn, 304, "Not Modified", "%s", ""); } else { handle_file_request(conn, path, &file); diff --git a/cpukit/mghttpd/mongoose.h b/cpukit/mghttpd/mongoose.h index ad7c40f2dd..787922a983 100644 --- a/cpukit/mghttpd/mongoose.h +++ b/cpukit/mghttpd/mongoose.h @@ -124,6 +124,19 @@ struct mg_callbacks { // Parameters: // status: HTTP error status code. int (*http_error)(struct mg_connection *, int status); + + // Called when mongoose needs to generate an HTTP etag. + // Implementing this callback allows a custom etag to be generated. If + // not implemented the standard etag generator is used which is the + // modification time as a hex value and the file size. + // Use this callback if the modification time cannot be controlled. + // Parameters: + // path: path to the file being requested + // etag: buffer to write the etag into + // etag_len: the length of the etag buffer + // Return value: + int (*http_etag)(const struct mg_connection *, + const char *path, char *etag, size_t etag_len); }; // Start web server. -- cgit v1.2.3