From: Peter Korsgaard <[email protected]>

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 <[email protected]>
---
 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

_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to