aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/Config.src8
-rw-r--r--networking/httpd.c56
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 */
}