[PATCH] httpd: add option to send files using gzip content-encoding if available

walter harms wharms at bfs.de
Fri Jul 23 16:04:37 UTC 2010



Peter Korsgaard schrieb:
> 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);

you could use
	        gzurl=xasprintf(%s.gz", url);
		fd = open(gzurl, O_RDONLY);
		free(gzurl);

> +		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 */
>  	}
>  


More information about the busybox mailing list