11#include <ulfius.h>
22#include <jansson.h>
33#include <sqlite3.h>
4+ #include <zlib.h>
45#include <stdio.h>
56#include <stdlib.h>
67#include <string.h>
1920static json_t * dataset_items = NULL ;
2021static char * json_large_response = NULL ;
2122static size_t json_large_len = 0 ;
23+ static unsigned char * json_large_gzipped = NULL ;
24+ static size_t json_large_gzip_len = 0 ;
2225
2326typedef struct {
2427 char name [256 ];
@@ -99,6 +102,26 @@ static void load_dataset(void) {
99102 dataset_items = root ;
100103}
101104
105+ static unsigned char * gzip_compress (const char * input , size_t in_len , size_t * out_len ) {
106+ uLongf bound = compressBound (in_len ) + 32 ;
107+ unsigned char * buf = malloc (bound );
108+ if (!buf ) return NULL ;
109+
110+ z_stream strm = {0 };
111+ if (deflateInit2 (& strm , Z_DEFAULT_COMPRESSION , Z_DEFLATED , 15 + 16 , 8 , Z_DEFAULT_STRATEGY ) != Z_OK ) {
112+ free (buf );
113+ return NULL ;
114+ }
115+ strm .next_in = (Bytef * )input ;
116+ strm .avail_in = in_len ;
117+ strm .next_out = buf ;
118+ strm .avail_out = bound ;
119+ deflate (& strm , Z_FINISH );
120+ * out_len = strm .total_out ;
121+ deflateEnd (& strm );
122+ return buf ;
123+ }
124+
102125static void load_dataset_large (void ) {
103126 size_t len ;
104127 char * data = read_file ("/data/dataset-large.json" , & len );
@@ -123,6 +146,9 @@ static void load_dataset_large(void) {
123146 json_large_response = json_dumps (resp , JSON_COMPACT );
124147 json_large_len = strlen (json_large_response );
125148 json_decref (resp );
149+
150+ /* Pre-compress for /compression endpoint */
151+ json_large_gzipped = gzip_compress (json_large_response , json_large_len , & json_large_gzip_len );
126152}
127153
128154static const char * mime_for_ext (const char * ext ) {
@@ -206,7 +232,14 @@ int cb_compression(const struct _u_request *request, struct _u_response *respons
206232 ulfius_set_string_body_response (response , 500 , "No dataset" );
207233 return U_CALLBACK_CONTINUE ;
208234 }
209- ulfius_set_binary_body_response (response , 200 , json_large_response , json_large_len );
235+ /* Serve gzip if client accepts it and we have a pre-compressed version */
236+ const char * accept_enc = u_map_get (request -> map_header , "Accept-Encoding" );
237+ if (json_large_gzipped && accept_enc && strstr (accept_enc , "gzip" )) {
238+ ulfius_set_binary_body_response (response , 200 , (const char * )json_large_gzipped , json_large_gzip_len );
239+ u_map_put (response -> map_header , "Content-Encoding" , "gzip" );
240+ } else {
241+ ulfius_set_binary_body_response (response , 200 , json_large_response , json_large_len );
242+ }
210243 u_map_put (response -> map_header , "Content-Type" , "application/json" );
211244 return U_CALLBACK_CONTINUE ;
212245}
0 commit comments