[PATCH] cpukit/mttpd: Add a callback to generate a per file HTTP etag.

Chris Johns chrisj at rtems.org
Thu Mar 8 04:13:36 UTC 2018


Closes #3323
---
 cpukit/mghttpd/mongoose.c | 19 +++++++++++++------
 cpukit/mghttpd/mongoose.h | 13 +++++++++++++
 2 files changed, 26 insertions(+), 6 deletions(-)

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.
-- 
2.14.1



More information about the devel mailing list