MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

gzip!

+131 -7
+4 -3
meson.build
··· 21 21 ) + files(module_files) 22 22 23 23 uuid_dep = dependency('uuid', required: true) 24 - zlib_dep = dependency('zlib', required: true) 25 24 llhttp = dependency('llhttp', required: true) 26 25 openssl_dep = dependency('openssl', required: true) 27 26 libsodium_dep = dependency('libsodium', required: true) ··· 41 40 tlsuv_opts.add_cmake_defines({'BUILD_TESTING': 'OFF'}) 42 41 tlsuv_dep = cmake.subproject('tlsuv', options: tlsuv_opts).dependency('tlsuv') 43 42 43 + zlib_dep = subproject('zlib-ng').get_variable('zlib_ng_dep') 44 44 bdwgc_dep = subproject('bdwgc').get_variable('bdwgc_dep') 45 45 uthash_dep = subproject('uthash').get_variable('uthash_dep') 46 46 yyjson_dep = subproject('yyjson').get_variable('yyjson_dep') ··· 74 74 build_date = run_command('date', '+%Y-%m-%d', check: true).stdout().strip() 75 75 76 76 version_conf = configuration_data() 77 - version_conf.set('ANT_VERSION', '0.1.0.11') 77 + version_conf.set('ANT_VERSION', '0.1.0.12') 78 78 version_conf.set('ANT_GIT_HASH', git_hash) 79 79 version_conf.set('ANT_BUILD_DATE', build_date) 80 80 ··· 116 116 ) 117 117 118 118 ant_deps = [ 119 + libffi_dep, 119 120 bdwgc_dep, uuid_dep, 120 121 llhttp, mongoose_dep, 121 122 libuv_dep, argtable3_dep, 122 123 tlsuv_dep, libsodium_dep, 123 124 yyjson_dep, minicoro_dep, 124 125 uuidv7_dep, openssl_dep, 125 - zlib_dep, uthash_dep, libffi_dep 126 + zlib_dep, uthash_dep 126 127 ] 127 128 128 129 if host_machine.system() == 'darwin'
+114 -4
src/modules/server.c
··· 4 4 #include <signal.h> 5 5 #include <unistd.h> 6 6 #include <uv.h> 7 + #include <zlib.h> 7 8 8 9 #include "ant.h" 9 10 #include "config.h" ··· 14 15 15 16 #define MAX_WRITE_HANDLES 1000 16 17 #define READ_BUFFER_SIZE 8192 18 + #define GZIP_MIN_SIZE 1024 17 19 18 20 typedef struct response_ctx_s { 19 21 int status; ··· 21 23 size_t body_len; 22 24 char *content_type; 23 25 int sent; 26 + int supports_gzip; 24 27 uv_tcp_t *client_handle; 25 28 struct response_ctx_s *next; 26 29 } response_ctx_t; ··· 66 69 } 67 70 } 68 71 72 + static int parse_accept_encoding(const char *buffer, size_t len) { 73 + const char *accept_encoding = strstr(buffer, "Accept-Encoding:"); 74 + if (!accept_encoding) accept_encoding = strstr(buffer, "accept-encoding:"); 75 + if (!accept_encoding) return 0; 76 + 77 + const char *line_end = strstr(accept_encoding, "\r\n"); 78 + if (!line_end) return 0; 79 + 80 + size_t header_len = line_end - accept_encoding; 81 + if (header_len > 1024) return 0; 82 + 83 + char header[1024]; 84 + memcpy(header, accept_encoding, header_len); 85 + header[header_len] = '\0'; 86 + 87 + return (strstr(header, "gzip") != NULL); 88 + } 89 + 90 + static int should_compress_content_type(const char *content_type) { 91 + if (!content_type) return 0; 92 + 93 + const char *compressible_types[] = { 94 + "text/html", 95 + "text/plain", 96 + "text/css", 97 + "text/javascript", 98 + "application/javascript", 99 + "application/json", 100 + "application/xml", 101 + "text/xml", 102 + NULL 103 + }; 104 + 105 + for (int i = 0; compressible_types[i] != NULL; i++) { 106 + if (strstr(content_type, compressible_types[i]) != NULL) return 1; 107 + } 108 + 109 + return 0; 110 + } 111 + 69 112 static const char* get_status_text(int status) { 70 113 switch (status) { 71 114 case 100: return "Continue"; ··· 146 189 char query[2048]; 147 190 char *body; 148 191 size_t body_len; 192 + int accepts_gzip; 149 193 } http_request_t; 150 194 151 195 static int parse_http_request(const char *buffer, size_t len, http_request_t *req) { ··· 178 222 req->query[0] = '\0'; 179 223 } 180 224 225 + req->accepts_gzip = parse_accept_encoding(buffer, len); 226 + 181 227 const char *body_start = strstr(buffer, "\r\n\r\n"); 182 228 if (body_start) { 183 229 body_start += 4; ··· 312 358 return js_mkundef(); 313 359 } 314 360 361 + static char* gzip_compress(const char *data, size_t data_len, size_t *compressed_len) { 362 + z_stream stream; 363 + memset(&stream, 0, sizeof(stream)); 364 + 365 + if (deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY) != Z_OK) { 366 + return NULL; 367 + } 368 + 369 + size_t bound = deflateBound(&stream, data_len); 370 + char *compressed = malloc(bound); 371 + if (!compressed) { 372 + deflateEnd(&stream); 373 + return NULL; 374 + } 375 + 376 + stream.next_in = (Bytef *)data; 377 + stream.avail_in = data_len; 378 + stream.next_out = (Bytef *)compressed; 379 + stream.avail_out = bound; 380 + 381 + if (deflate(&stream, Z_FINISH) != Z_STREAM_END) { 382 + free(compressed); 383 + deflateEnd(&stream); 384 + return NULL; 385 + } 386 + 387 + *compressed_len = stream.total_out; 388 + deflateEnd(&stream); 389 + 390 + return compressed; 391 + } 392 + 315 393 static void on_write(uv_write_t *req, int status) { 316 394 write_req_t *wr = (write_req_t *)req; 317 395 if (status) fprintf(stderr, "Write error: %s\n", uv_strerror(status)); ··· 320 398 } 321 399 322 400 static void send_response(uv_stream_t *client, response_ctx_t *res_ctx) { 401 + char *body_to_send = res_ctx->body; 402 + size_t body_len_to_send = res_ctx->body_len; 403 + char *compressed = NULL; 404 + int use_gzip = 0; 405 + 406 + if (res_ctx->supports_gzip && 407 + res_ctx->body_len >= GZIP_MIN_SIZE && 408 + should_compress_content_type(res_ctx->content_type)) { 409 + 410 + size_t compressed_len; 411 + compressed = gzip_compress(res_ctx->body, res_ctx->body_len, &compressed_len); 412 + 413 + if (compressed && compressed_len < res_ctx->body_len) { 414 + body_to_send = compressed; 415 + body_len_to_send = compressed_len; 416 + use_gzip = 1; 417 + } else if (compressed) { 418 + free(compressed); 419 + compressed = NULL; 420 + } 421 + } 422 + 323 423 char header[4096]; 324 424 int header_len = snprintf(header, sizeof(header), 325 425 "HTTP/1.1 %d %s\r\n" 326 426 "Content-Type: %s\r\n" 327 427 "Content-Length: %zu\r\n" 428 + "%s" 328 429 "Connection: close\r\n" 329 430 "\r\n", 330 431 res_ctx->status, 331 432 get_status_text(res_ctx->status), 332 433 res_ctx->content_type ? res_ctx->content_type : "text/plain", 333 - res_ctx->body_len 434 + body_len_to_send, 435 + use_gzip ? "Content-Encoding: gzip\r\n" : "" 334 436 ); 335 437 336 - size_t total_len = header_len + res_ctx->body_len; 438 + size_t total_len = header_len + body_len_to_send; 337 439 338 440 write_req_t *write_req = malloc(sizeof(write_req_t)); 339 - if (!write_req) return; 441 + if (!write_req) { 442 + if (compressed) free(compressed); 443 + return; 444 + } 340 445 341 446 char *response = malloc(total_len); 342 447 if (!response) { 343 448 free(write_req); 449 + if (compressed) free(compressed); 344 450 return; 345 451 } 346 452 347 453 memcpy(response, header, header_len); 348 - if (res_ctx->body_len > 0) memcpy(response + header_len, res_ctx->body, res_ctx->body_len); 454 + if (body_len_to_send > 0) memcpy(response + header_len, body_to_send, body_len_to_send); 455 + 456 + if (compressed) free(compressed); 349 457 350 458 write_req->buf = uv_buf_init(response, total_len); 351 459 uv_write((uv_write_t *)write_req, client, &write_req->buf, 1, on_write); ··· 367 475 res_ctx->body_len = 0; 368 476 res_ctx->content_type = "text/plain"; 369 477 res_ctx->sent = 0; 478 + res_ctx->supports_gzip = http_req->accepts_gzip; 370 479 res_ctx->client_handle = &client->handle; 371 480 res_ctx->next = NULL; 372 481 ··· 501 610 res_ctx->body_len = strlen(res_ctx->body); 502 611 res_ctx->content_type = "text/plain"; 503 612 res_ctx->sent = 1; 613 + res_ctx->supports_gzip = 0; 504 614 res_ctx->client_handle = &client->handle; 505 615 res_ctx->next = client->server->pending_responses; 506 616 client->server->pending_responses = res_ctx;
+13
subprojects/zlib-ng.wrap
··· 1 + [wrap-file] 2 + directory = zlib-ng-2.3.2 3 + source_url = https://github.com/zlib-ng/zlib-ng/archive/refs/tags/2.3.2.tar.gz 4 + source_filename = zlib-ng-2.3.2.tar.gz 5 + source_hash = 6a0561b50b8f5f6434a6a9e667a67026f2b2064a1ffa959c6b2dae320161c2a8 6 + source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/zlib-ng_2.3.2-1/zlib-ng-2.3.2.tar.gz 7 + patch_filename = zlib-ng_2.3.2-1_patch.zip 8 + patch_url = https://wrapdb.mesonbuild.com/v2/zlib-ng_2.3.2-1/get_patch 9 + patch_hash = 110f10f762f89101c7e6c1d10c6e02bbb3364165cccf557bec4d906018978d98 10 + wrapdb_version = 2.3.2-1 11 + 12 + [provide] 13 + dependency_names = zlib-ng