diff options
-rw-r--r-- | networking/Config.src | 8 | ||||
-rw-r--r-- | networking/httpd.c | 56 |
2 files changed, 60 insertions, 4 deletions
diff --git a/networking/Config.src b/networking/Config.src index 2d29c423a..8604c53e9 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 12bad597a..cad45cd5d 100644 --- a/networking/httpd.c +++ b/networking/httpd.c @@ -277,6 +277,10 @@ struct globals { #if ENABLE_FEATURE_HTTPD_PROXY Htaccess_Proxy *proxy; #endif +#if ENABLE_FEATURE_HTTPD_GZIP + /* client can handle gzip / we are going to send gzip */ + smallint content_gzip; +#endif }; #define G (*ptr_to_globals) #define verbose (G.verbose ) @@ -319,6 +323,11 @@ enum { #define hdr_cnt (G.hdr_cnt ) #define http_error_page (G.http_error_page ) #define proxy (G.proxy ) +#if ENABLE_FEATURE_HTTPD_GZIP +# define content_gzip (G.content_gzip ) +#else +# define content_gzip 0 +#endif #define INIT_G() do { \ SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ IF_FEATURE_HTTPD_BASIC_AUTH(g_realm = "Web Server Authentication";) \ @@ -1027,10 +1036,14 @@ static void send_headers(int responseNum) #endif "Last-Modified: %s\r\n%s %"OFF_FMT"u\r\n", tmp_str, - "Content-length:", + content_gzip ? "Transfer-length:" : "Content-length:", file_size ); } + + if (content_gzip) + len += sprintf(iobuf + len, "Content-Encoding: gzip\r\n"); + iobuf[len++] = '\r'; iobuf[len++] = '\n'; if (infoString) { @@ -1500,7 +1513,22 @@ static NOINLINE void send_file_and_exit(const char *url, int what) int fd; ssize_t count; - fd = open(url, O_RDONLY); + if (content_gzip) { + /* does <url>.gz exist? Then use it instead */ + char *gzurl = xasprintf("%s.gz", url); + fd = open(gzurl, O_RDONLY); + free(gzurl); + if (fd != -1) { + struct stat sb; + fstat(fd, &sb); + file_size = sb.st_size; + } else { + IF_FEATURE_HTTPD_GZIP(content_gzip = 0;) + fd = open(url, O_RDONLY); + } + } else { + fd = open(url, O_RDONLY); + } if (fd < 0) { if (DEBUG) bb_perror_msg("can't open '%s'", url); @@ -1583,8 +1611,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) - range_start = 0; /* err pages and ranges don't mix */ + if (what == SEND_BODY /* err pages and ranges don't mix */ + || content_gzip /* we are sending compressed page: can't do ranges */ ///why? + ) { + range_start = 0; + } range_len = MAXINT(off_t); if (range_start) { if (!range_end) { @@ -2048,6 +2079,23 @@ 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) { + ///is "Accept-Encoding: compress,gzip" valid? + // (that is, no space after ',') - + // this code won't handle that + s = skip_whitespace(s); + if (STRNCASECMP(s, "gzip") == 0) + content_gzip = 1; + /* Note: we do not support "gzip;q=0" + * method of _disabling_ gzip + * delivery */ + s = skip_non_whitespace(s); + } + } +#endif } /* while extra header reading */ } |