[PATCH] httpd: add option to send files using gzip content-encoding if available
Peter Korsgaard
jacmet at sunsite.dk
Fri Jul 23 15:22:12 UTC 2010
From: Peter Korsgaard <peter.korsgaard at barco.com>
With this option enabled, httpd sends compressed data if supported by
the client and a pre-compressed <file>.gz is available.
bloat-o-meter:
function old new delta
send_file_and_exit 667 833 +166
handle_incoming_and_exit 2983 3121 +138
.rodata 126806 126876 +70
send_headers 754 803 +49
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 4/0 up/down: 423/0) Total: 423 bytes
Signed-off-by: Peter Korsgaard <peter.korsgaard at barco.com>
---
networking/Config.src | 8 +++++++
networking/httpd.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 58 insertions(+), 1 deletions(-)
diff --git a/networking/Config.src b/networking/Config.src
index 2d29c42..8604c53 100644
--- a/networking/Config.src
+++ b/networking/Config.src
@@ -270,6 +270,14 @@ config FEATURE_HTTPD_PROXY
Then a request to /url/myfile will be forwarded to
http://hostname[:port]/new/path/myfile.
+config FEATURE_HTTPD_GZIP
+ bool "Support for GZIP content encoding"
+ default y
+ depends on HTTPD
+ help
+ Makes httpd send files using GZIP content encoding if the
+ client supports it and a pre-compressed <file>.gz exists.
+
config IFCONFIG
bool "ifconfig"
default y
diff --git a/networking/httpd.c b/networking/httpd.c
index 8ad7e88..55b11c8 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -284,6 +284,10 @@ struct globals {
#if ENABLE_FEATURE_HTTPD_PROXY
Htaccess_Proxy *proxy;
#endif
+#if ENABLE_FEATURE_HTTPD_GZIP
+ smallint supports_gzip; /* client can handle gzip */
+ smallint gzipped; /* file is gzipped */
+#endif
};
#define G (*ptr_to_globals)
#define verbose (G.verbose )
@@ -326,6 +330,8 @@ enum {
#define hdr_cnt (G.hdr_cnt )
#define http_error_page (G.http_error_page )
#define proxy (G.proxy )
+#define supports_gzip (G.supports_gzip )
+#define gzipped (G.gzipped )
#define INIT_G() do { \
SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
IF_FEATURE_HTTPD_BASIC_AUTH(g_realm = "Web Server Authentication";) \
@@ -1034,10 +1040,18 @@ static void send_headers(int responseNum)
#endif
"Last-Modified: %s\r\n%s %"OFF_FMT"u\r\n",
tmp_str,
+#if ENABLE_FEATURE_HTTPD_GZIP
+ gzipped ? "Transfer-length:" :
+#endif
"Content-length:",
file_size
);
}
+#if ENABLE_FEATURE_HTTPD_GZIP
+ if (gzipped)
+ len += sprintf(iobuf + len, "Content-Encoding: gzip\r\n");
+#endif
+
iobuf[len++] = '\r';
iobuf[len++] = '\n';
if (infoString) {
@@ -1507,6 +1521,26 @@ static NOINLINE void send_file_and_exit(const char *url, int what)
int fd;
ssize_t count;
+#if ENABLE_FEATURE_HTTPD_GZIP
+ if (supports_gzip) {
+ char *gzurl;
+
+ /* does <url>.gz exist? Then use it instead */
+ gzurl = alloca(strlen(url) + strlen(".gz") + 1);
+ sprintf(gzurl, "%s.gz", url);
+ fd = open(gzurl, O_RDONLY);
+ if (fd != -1) {
+ struct stat sb;
+
+ fstat(fd, &sb);
+ file_size = sb.st_size;
+ gzipped = 1;
+ }
+ else
+ fd = open(url, O_RDONLY);
+ }
+ else
+#endif
fd = open(url, O_RDONLY);
if (fd < 0) {
if (DEBUG)
@@ -1590,7 +1624,11 @@ static NOINLINE void send_file_and_exit(const char *url, int what)
url, found_mime_type);
#if ENABLE_FEATURE_HTTPD_RANGES
- if (what == SEND_BODY)
+ if (what == SEND_BODY
+#if ENABLE_FEATURE_HTTPD_GZIP
+ || gzipped
+#endif
+ )
range_start = 0; /* err pages and ranges don't mix */
range_len = MAXINT(off_t);
if (range_start) {
@@ -2055,6 +2093,17 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
}
}
#endif
+#if ENABLE_FEATURE_HTTPD_GZIP
+ if (STRNCASECMP(iobuf, "Accept-Encoding:") == 0) {
+ char *s = iobuf + sizeof("Accept-Encoding:")-1;
+ while (*s) {
+ s = skip_whitespace(s);
+ if (STRNCASECMP(s, "gzip") == 0)
+ supports_gzip = 1;
+ s = skip_non_whitespace(s);
+ }
+ }
+#endif
} /* while extra header reading */
}
--
1.7.1
More information about the busybox
mailing list