uhttpd: serve precompressed files

The aredn project benefits from precompressed files given
mesh nodes are typically long distant RF links and UI
is accessed remotely.  uhttpd will look for the filename
requested first, then if not found, look for filename.gz
and update content header passed back as appropriate.

https://patchwork.ozlabs.org/patch/514918/
This commit is contained in:
Adrian Kotelba 2018-11-22 05:24:32 +00:00 committed by Joe AE6XE
parent 311d32a943
commit f06202160b
2 changed files with 132 additions and 0 deletions

View File

@ -0,0 +1,131 @@
Index: openwrt/package/network/services/uhttpd/patches/001-uhttpd-compress.patch
===================================================================
--- /dev/null
+++ openwrt/package/network/services/uhttpd/patches/001-uhttpd-compress.patch
@@ -0,0 +1,113 @@
+--- a/file.c
++++ b/file.c
+@@ -139,6 +139,7 @@
+ int docroot_len = strlen(docroot);
+ char *pathptr = NULL;
+ bool slash;
++ bool precompressed = 0;
+
+ int i = 0;
+ int len;
+@@ -198,11 +199,27 @@
+ continue;
+
+ /* test current path */
+- if (stat(path_phys, &p.stat))
++ if (stat(path_phys, &p.stat) == 0) {
++ snprintf(path_info, sizeof(path_info), "%s", uh_buf + i);
++ break;
++ }
++
++ pathptr = path_phys + strlen(path_phys);
++
++ /* try to locate precompressed file */
++ len = path_phys + sizeof(path_phys) - pathptr - 1;
++ if (strlen(".gz") > len)
+ continue;
+
+- snprintf(path_info, sizeof(path_info), "%s", uh_buf + i);
+- break;
++ strcpy(pathptr, ".gz");
++ if (stat(path_phys, &p.stat) == 0) {
++ snprintf(path_info, sizeof(path_info), "%s", uh_buf + i);
++ precompressed = 1;
++ break;
++ }
++
++ *pathptr = 0;
++
+ }
+
+ /* check whether found path is within docroot */
+@@ -217,6 +234,7 @@
+ p.phys = path_phys;
+ p.name = &path_phys[docroot_len];
+ p.info = path_info[0] ? path_info : NULL;
++ p.compressed = precompressed;
+ return &p;
+ }
+
+@@ -266,9 +284,27 @@
+ *pathptr = 0;
+ }
+
++ /* try to locate precompressed index file */
++ len = path_phys + sizeof(path_phys) - pathptr - 1;
++ list_for_each_entry(idx, &index_files, list) {
++ if (strlen(idx->name) + strlen(".gz") > len)
++ continue;
++
++ strcpy(pathptr, idx->name);
++ strcpy(pathptr + strlen(idx->name), ".gz");
++ if (!stat(path_phys, &s) && (s.st_mode & S_IFREG)) {
++ memcpy(&p.stat, &s, sizeof(p.stat));
++ precompressed = 1;
++ break;
++ }
++
++ *pathptr = 0;
++ }
++
+ p.root = docroot;
+ p.phys = path_phys;
+ p.name = &path_phys[docroot_len];
++ p.compressed = precompressed;
+
+ return p.phys ? &p : NULL;
+ }
+@@ -584,6 +620,8 @@
+
+ static void uh_file_data(struct client *cl, struct path_info *pi, int fd)
+ {
++ static char name[PATH_MAX];
++
+ /* test preconditions */
+ if (!cl->dispatch.no_cache &&
+ (!uh_file_if_modified_since(cl, &pi->stat) ||
+@@ -600,8 +638,15 @@
+ /* write status */
+ uh_file_response_200(cl, &pi->stat);
+
++ strcpy(name, pi->name);
++
++ if (pi->compressed) {
++ name[strlen(name) - strlen(".gz")] = 0;
++ ustream_printf(cl->us, "Content-Encoding: gzip\r\n");
++ }
++
+ ustream_printf(cl->us, "Content-Type: %s\r\n",
+- uh_file_mime_lookup(pi->name));
++ uh_file_mime_lookup(name));
+
+ ustream_printf(cl->us, "Content-Length: %" PRIu64 "\r\n\r\n",
+ pi->stat.st_size);
+--- a/uhttpd.h
++++ b/uhttpd.h
+@@ -147,6 +147,7 @@
+ const char *info;
+ const char *query;
+ bool redirected;
++ bool compressed;
+ struct stat stat;
+ const struct interpreter *ip;
+ };
Index: openwrt/package/network/services/uhttpd/Makefile
===================================================================
--- openwrt.orig/package/network/services/uhttpd/Makefile
+++ openwrt/package/network/services/uhttpd/Makefile
@@ -8,7 +8,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=uhttpd
-PKG_RELEASE:=1
+PKG_RELEASE:=AREDN1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=$(PROJECT_GIT)/project/uhttpd.git

View File

@ -15,3 +15,4 @@
709-iperf-fw-restart.patch 709-iperf-fw-restart.patch
710-no-ping6-traceroute6.patch 710-no-ping6-traceroute6.patch
711-nano-xw-switch-config.patch 711-nano-xw-switch-config.patch
712-uhhtpd-compress.patch