quark-precompression-20200308-3c7049e.diff (3325B)
1 From 668df28967b8abd2893383e4d20b16cfe99dfdeb Mon Sep 17 00:00:00 2001 2 From: guysv <sviryguy@gmail.com> 3 Date: Sun, 8 Mar 2020 18:40:07 +0200 4 Subject: [PATCH] Add support for precomputed compression 5 6 If a client indicates that it supports gzip, then look for a `.gz` 7 variation of requested file. If such gzipped file exists, send it 8 instead and set the appropriate headers. 9 10 Range requests and dirlist requests are not supported. 11 --- 12 http.c | 24 ++++++++++++++++++++++-- 13 http.h | 1 + 14 resp.c | 5 +++-- 15 resp.h | 2 +- 16 4 files changed, 27 insertions(+), 5 deletions(-) 17 18 diff --git a/http.c b/http.c 19 index efc4136..a654514 100644 20 --- a/http.c 21 +++ b/http.c 22 @@ -25,6 +25,7 @@ const char *req_field_str[] = { 23 [REQ_HOST] = "Host", 24 [REQ_RANGE] = "Range", 25 [REQ_MOD] = "If-Modified-Since", 26 + [REQ_ENCODE] = "Accept-Encoding", 27 }; 28 29 const char *req_method_str[] = { 30 @@ -349,7 +350,7 @@ enum status 31 http_send_response(int fd, struct request *r) 32 { 33 struct in6_addr res; 34 - struct stat st; 35 + struct stat st, gzst; 36 struct tm tm; 37 size_t len, i; 38 off_t lower, upper; 39 @@ -604,5 +605,24 @@ http_send_response(int fd, struct request *r) 40 } 41 } 42 43 - return resp_file(fd, RELPATH(realtarget), r, &st, mime, lower, upper); 44 + /* encoding-compression */ 45 + if (r->field[REQ_ENCODE][0] && !r->field[REQ_RANGE][0]) { 46 + for (p = r->field[REQ_ENCODE]; p; p = strchr(p, ','), p ? p++ : p) { 47 + /* skip whitespace */ 48 + for (; *p == ' ' || *p == '\t'; p++) 49 + ; 50 + if (!strncasecmp(p, "gzip", sizeof("gzip")-1) && 51 + !esnprintf(tmptarget, sizeof(tmptarget), "%s%s", realtarget, 52 + ".gz") && 53 + !stat(RELPATH(tmptarget), &gzst) && 54 + S_ISREG(gzst.st_mode)) { 55 + lower = 0; 56 + upper = gzst.st_size-1; 57 + return resp_file(fd, RELPATH(tmptarget), r, &gzst, mime, 58 + "Content-Encoding: gzip\r\n", lower, upper); 59 + } 60 + } 61 + } 62 + 63 + return resp_file(fd, RELPATH(realtarget), r, &st, mime, "", lower, upper); 64 } 65 diff --git a/http.h b/http.h 66 index cd1ba22..26ced90 100644 67 --- a/http.h 68 +++ b/http.h 69 @@ -11,6 +11,7 @@ enum req_field { 70 REQ_HOST, 71 REQ_RANGE, 72 REQ_MOD, 73 + REQ_ENCODE, 74 NUM_REQ_FIELDS, 75 }; 76 77 diff --git a/resp.c b/resp.c 78 index 3075c28..bf35ac8 100644 79 --- a/resp.c 80 +++ b/resp.c 81 @@ -111,7 +111,7 @@ cleanup: 82 83 enum status 84 resp_file(int fd, char *name, struct request *r, struct stat *st, char *mime, 85 - off_t lower, off_t upper) 86 + char *encoding, off_t lower, off_t upper) 87 { 88 FILE *fp; 89 enum status s; 90 @@ -142,10 +142,11 @@ resp_file(int fd, char *name, struct request *r, struct stat *st, char *mime, 91 "Connection: close\r\n" 92 "Last-Modified: %s\r\n" 93 "Content-Type: %s\r\n" 94 + "%s" 95 "Content-Length: %zu\r\n", 96 s, status_str[s], timestamp(time(NULL), t1), 97 timestamp(st->st_mtim.tv_sec, t2), mime, 98 - upper - lower + 1) < 0) { 99 + encoding, upper - lower + 1) < 0) { 100 s = S_REQUEST_TIMEOUT; 101 goto cleanup; 102 } 103 diff --git a/resp.h b/resp.h 104 index d5928ef..ccfaaad 100644 105 --- a/resp.h 106 +++ b/resp.h 107 @@ -9,6 +9,6 @@ 108 109 enum status resp_dir(int, char *, struct request *); 110 enum status resp_file(int, char *, struct request *, struct stat *, char *, 111 - off_t, off_t); 112 + char *, off_t, off_t); 113 114 #endif /* RESP_H */ 115 -- 116 2.25.1 117