From: Jaroslav Kysela Date: Thu, 14 May 2015 12:30:48 +0000 (+0200) Subject: http server: gzip JSON responses (if possible) X-Git-Tag: v4.1~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=496f14d5d219d048668669df4d0d106338a784fa;p=thirdparty%2Ftvheadend.git http server: gzip JSON responses (if possible) --- diff --git a/src/filebundle.c b/src/filebundle.c index dbc2b16ad..ff4c28456 100644 --- a/src/filebundle.c +++ b/src/filebundle.c @@ -16,8 +16,8 @@ * along with this program. If not, see . */ -#include "filebundle.h" #include "tvheadend.h" +#include "filebundle.h" #include #include @@ -77,8 +77,8 @@ struct filebundle_file * Compression/Decompression * *************************************************************************/ -#if (ENABLE_ZLIB && ENABLE_BUNDLE) -static uint8_t *_fb_inflate ( const uint8_t *data, size_t size, size_t orig ) +#if ENABLE_ZLIB +uint8_t *gzip_inflate ( const uint8_t *data, size_t size, size_t orig ) { int err; z_stream zstr; @@ -108,7 +108,7 @@ static uint8_t *_fb_inflate ( const uint8_t *data, size_t size, size_t orig ) #endif #if ENABLE_ZLIB -static uint8_t *_fb_deflate ( const uint8_t *data, size_t orig, size_t *size ) +uint8_t *gzip_deflate ( const uint8_t *data, size_t orig, size_t *size ) { int err; z_stream zstr; @@ -125,7 +125,7 @@ static uint8_t *_fb_deflate ( const uint8_t *data, size_t orig, size_t *size ) zstr.avail_out = orig; zstr.next_out = bufout; - /* Decompress */ + /* Compress */ while (1) { err = deflate(&zstr, Z_FINISH); @@ -395,7 +395,7 @@ fb_file *fb_open2 #if (ENABLE_ZLIB && ENABLE_BUNDLE) ret->gzip = 0; ret->size = fb->f.orig; - ret->buf = _fb_inflate(fb->f.data, fb->f.size, fb->f.orig); + ret->buf = gzip_inflate(fb->f.data, fb->f.size, fb->f.orig); if (!ret->buf) { free(ret); ret = NULL; @@ -432,12 +432,12 @@ fb_file *fb_open2 if (ret->type == FB_BUNDLE) { const uint8_t *data; data = ret->b.root->f.data; - ret->buf = _fb_deflate(data, ret->size, &ret->size); + ret->buf = gzip_deflate(data, ret->size, &ret->size); } else { uint8_t *data = malloc(ret->size); ssize_t c = fread(data, 1, ret->size, ret->d.cur); if (c == ret->size) - ret->buf = _fb_deflate(data, ret->size, &ret->size); + ret->buf = gzip_deflate(data, ret->size, &ret->size); fclose(ret->d.cur); ret->d.cur = NULL; free(data); diff --git a/src/filebundle.h b/src/filebundle.h index 006323434..ea515cfe1 100644 --- a/src/filebundle.h +++ b/src/filebundle.h @@ -82,6 +82,10 @@ extern filebundle_entry_t *filebundle_root; /* Miscellaneous */ int fb_stat ( const char *path, struct filebundle_stat *st ); +#if ENABLE_ZLIB +uint8_t *gzip_deflate ( const uint8_t *data, size_t orig, size_t *size ); +uint8_t *gzip_inflate ( const uint8_t *data, size_t size, size_t orig ); +#endif /* Directory processing wrappers */ fb_dir *fb_opendir ( const char *path ); diff --git a/src/http.c b/src/http.c index 70e912011..31feb40a9 100644 --- a/src/http.c +++ b/src/http.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -33,6 +34,7 @@ #include "tvheadend.h" #include "tcp.h" #include "http.h" +#include "filebundle.h" #include "access.h" #include "notify.h" #include "channels.h" @@ -310,7 +312,34 @@ http_send_header(http_connection_t *hc, int rc, const char *content, tcp_write_queue(hc->hc_fd, &hdrs); } +/* + * + */ +int +http_encoding_valid(http_connection_t *hc, const char *encoding) +{ + const char *accept; + size_t l = strlen(encoding); + size_t i; + + accept = http_arg_get(&hc->hc_args, "accept-encoding"); + if (!accept) + return 0; + while (*accept) { + for (i = 0; i < l; i++) + if (tolower(accept[i]) != encoding[i]) + break; + if (i < l) + continue; + accept += l; + while (*accept == ' ') + accept++; + if (*accept == ',' || *accept == '\0') + return 1; + } + return 0; +} /** * Transmit a HTTP reply @@ -319,13 +348,29 @@ static void http_send_reply(http_connection_t *hc, int rc, const char *content, const char *encoding, const char *location, int maxage) { - http_send_header(hc, rc, content, hc->hc_reply.hq_size, + size_t size = hc->hc_reply.hq_size; + uint8_t *data = NULL; + +#if ENABLE_ZLIB + if (http_encoding_valid(hc, "gzip") && encoding == NULL && size > 256) { + uint8_t *data2 = (uint8_t *)htsbuf_to_string(&hc->hc_reply); + data = gzip_deflate(data2, size, &size); + free(data2); + encoding = "gzip"; + } +#endif + + http_send_header(hc, rc, content, size, encoding, location, maxage, 0, NULL, NULL); - if(hc->hc_no_output) - return; + if(!hc->hc_no_output) { + if (data == NULL) + tcp_write_queue(hc->hc_fd, &hc->hc_reply); + else + tvh_write(hc->hc_fd, data, size); + } - tcp_write_queue(hc->hc_fd, &hc->hc_reply); + free(data); } diff --git a/src/http.h b/src/http.h index 4dd0c0686..147032ec2 100644 --- a/src/http.h +++ b/src/http.h @@ -184,6 +184,8 @@ int http_tokenize(char *buf, char **vec, int vecsize, int delimiter); void http_error(http_connection_t *hc, int error); +int http_encoding_valid(http_connection_t *hc, const char *encoding); + void http_output_html(http_connection_t *hc); void http_output_content(http_connection_t *hc, const char *content);