]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
http server: gzip JSON responses (if possible)
authorJaroslav Kysela <perex@perex.cz>
Thu, 14 May 2015 12:30:48 +0000 (14:30 +0200)
committerJaroslav Kysela <perex@perex.cz>
Thu, 14 May 2015 12:30:48 +0000 (14:30 +0200)
src/filebundle.c
src/filebundle.h
src/http.c
src/http.h

index dbc2b16ad4bf368340bb4ebab7be28e9674737ef..ff4c284563cf69fe37021d274929882d9cf00bb6 100644 (file)
@@ -16,8 +16,8 @@
  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "filebundle.h"
 #include "tvheadend.h"
+#include "filebundle.h"
 
 #include <unistd.h>
 #include <stdlib.h>
@@ -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);
index 0063234345b88135b2d7f63afcc6195f4b32e8e1..ea515cfe1590899735521ae23ff365e99aa38d1f 100644 (file)
@@ -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 );
index 70e912011804526325fab745a7b39953a601d66b..31feb40a9e4faaf4a0f212b789746e6086c0ead2 100644 (file)
@@ -23,6 +23,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <stdarg.h>
+#include <ctype.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <signal.h>
@@ -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);
 }
 
 
index 4dd0c06865924e7cacc5f014702089e8c7159df5..147032ec285dac71f9c72337e30d3114dd5de2fa 100644 (file)
@@ -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);