diff options
| author | 2023-07-02 11:11:01 +0200 | |
|---|---|---|
| committer | 2023-07-02 11:11:01 +0200 | |
| commit | d343b40ee553de8d98c18d3547e6c9b12ab96b48 (patch) | |
| tree | 2f2d9ab495d2ad4e8187f31530d8019968b905bf | |
| parent | Fixed footer link. (diff) | |
| download | snac2-d343b40ee553de8d98c18d3547e6c9b12ab96b48.tar.gz snac2-d343b40ee553de8d98c18d3547e6c9b12ab96b48.tar.xz snac2-d343b40ee553de8d98c18d3547e6c9b12ab96b48.zip | |
Added HTTP caching to static data.
| -rw-r--r-- | data.c | 39 | ||||
| -rw-r--r-- | html.c | 10 | ||||
| -rw-r--r-- | httpd.c | 6 | ||||
| -rw-r--r-- | snac.h | 4 |
4 files changed, 45 insertions, 14 deletions
| @@ -1533,19 +1533,44 @@ xs_str *_static_fn(snac *snac, const char *id) | |||
| 1533 | } | 1533 | } |
| 1534 | 1534 | ||
| 1535 | 1535 | ||
| 1536 | int static_get(snac *snac, const char *id, xs_val **data, int *size) | 1536 | int static_get(snac *snac, const char *id, xs_val **data, int *size, |
| 1537 | const char *inm, xs_str **etag) | ||
| 1537 | /* returns static content */ | 1538 | /* returns static content */ |
| 1538 | { | 1539 | { |
| 1539 | xs *fn = _static_fn(snac, id); | 1540 | xs *fn = _static_fn(snac, id); |
| 1540 | FILE *f; | ||
| 1541 | int status = 404; | 1541 | int status = 404; |
| 1542 | 1542 | ||
| 1543 | if (fn && (f = fopen(fn, "rb")) != NULL) { | 1543 | if (fn) { |
| 1544 | *size = XS_ALL; | 1544 | double tm = mtime(fn); |
| 1545 | *data = xs_read(f, size); | ||
| 1546 | fclose(f); | ||
| 1547 | 1545 | ||
| 1548 | status = 200; | 1546 | if (tm > 0.0) { |
| 1547 | /* file exists; build the etag */ | ||
| 1548 | xs *e = xs_fmt("W/\"snac-%.0lf\"", tm); | ||
| 1549 | |||
| 1550 | /* if if-none-match is set, check if it's the same */ | ||
| 1551 | if (!xs_is_null(inm) && strcmp(e, inm) == 0) { | ||
| 1552 | /* client has the newest version */ | ||
| 1553 | status = 304; | ||
| 1554 | } | ||
| 1555 | else { | ||
| 1556 | /* newer or never downloaded; read the full file */ | ||
| 1557 | FILE *f; | ||
| 1558 | |||
| 1559 | if ((f = fopen(fn, "rb")) != NULL) { | ||
| 1560 | *size = XS_ALL; | ||
| 1561 | *data = xs_read(f, size); | ||
| 1562 | fclose(f); | ||
| 1563 | |||
| 1564 | status = 200; | ||
| 1565 | } | ||
| 1566 | } | ||
| 1567 | |||
| 1568 | /* if caller wants the etag, return it */ | ||
| 1569 | if (etag != NULL) | ||
| 1570 | *etag = xs_dup(e); | ||
| 1571 | |||
| 1572 | srv_debug(1, xs_fmt("static_get(): %d %s %s", status, id, e)); | ||
| 1573 | } | ||
| 1549 | } | 1574 | } |
| 1550 | 1575 | ||
| 1551 | return status; | 1576 | return status; |
| @@ -226,7 +226,7 @@ d_char *html_user_header(snac *snac, d_char *s, int local) | |||
| 226 | int size; | 226 | int size; |
| 227 | 227 | ||
| 228 | /* try to open the user css */ | 228 | /* try to open the user css */ |
| 229 | if (!valid_status(static_get(snac, "style.css", &css, &size))) { | 229 | if (!valid_status(static_get(snac, "style.css", &css, &size, NULL, NULL))) { |
| 230 | /* it's not there; try to open the server-wide css */ | 230 | /* it's not there; try to open the server-wide css */ |
| 231 | FILE *f; | 231 | FILE *f; |
| 232 | xs *g_css_fn = xs_fmt("%s/style.css", srv_basedir); | 232 | xs *g_css_fn = xs_fmt("%s/style.css", srv_basedir); |
| @@ -1542,7 +1542,7 @@ xs_str *html_notifications(snac *snac) | |||
| 1542 | 1542 | ||
| 1543 | 1543 | ||
| 1544 | int html_get_handler(const xs_dict *req, const char *q_path, | 1544 | int html_get_handler(const xs_dict *req, const char *q_path, |
| 1545 | char **body, int *b_size, char **ctype) | 1545 | char **body, int *b_size, char **ctype, xs_str **etag) |
| 1546 | { | 1546 | { |
| 1547 | char *accept = xs_dict_get(req, "accept"); | 1547 | char *accept = xs_dict_get(req, "accept"); |
| 1548 | int status = 404; | 1548 | int status = 404; |
| @@ -1695,10 +1695,12 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 1695 | char *id = xs_list_get(l, 1); | 1695 | char *id = xs_list_get(l, 1); |
| 1696 | int sz; | 1696 | int sz; |
| 1697 | 1697 | ||
| 1698 | if (valid_status(static_get(&snac, id, body, &sz))) { | 1698 | status = static_get(&snac, id, body, &sz, |
| 1699 | xs_dict_get(req, "if-none-match"), etag); | ||
| 1700 | |||
| 1701 | if (valid_status(status)) { | ||
| 1699 | *b_size = sz; | 1702 | *b_size = sz; |
| 1700 | *ctype = xs_mime_by_ext(id); | 1703 | *ctype = xs_mime_by_ext(id); |
| 1701 | status = 200; | ||
| 1702 | } | 1704 | } |
| 1703 | } | 1705 | } |
| 1704 | else | 1706 | else |
| @@ -156,6 +156,7 @@ void httpd_connection(FILE *f) | |||
| 156 | xs *headers = NULL; | 156 | xs *headers = NULL; |
| 157 | xs *q_path = NULL; | 157 | xs *q_path = NULL; |
| 158 | xs *payload = NULL; | 158 | xs *payload = NULL; |
| 159 | xs *etag = NULL; | ||
| 159 | int p_size = 0; | 160 | int p_size = 0; |
| 160 | char *p; | 161 | char *p; |
| 161 | 162 | ||
| @@ -198,7 +199,7 @@ void httpd_connection(FILE *f) | |||
| 198 | #endif /* NO_MASTODON_API */ | 199 | #endif /* NO_MASTODON_API */ |
| 199 | 200 | ||
| 200 | if (status == 0) | 201 | if (status == 0) |
| 201 | status = html_get_handler(req, q_path, &body, &b_size, &ctype); | 202 | status = html_get_handler(req, q_path, &body, &b_size, &ctype, &etag); |
| 202 | } | 203 | } |
| 203 | else | 204 | else |
| 204 | if (strcmp(method, "POST") == 0) { | 205 | if (strcmp(method, "POST") == 0) { |
| @@ -263,6 +264,9 @@ void httpd_connection(FILE *f) | |||
| 263 | headers = xs_dict_append(headers, "content-type", ctype); | 264 | headers = xs_dict_append(headers, "content-type", ctype); |
| 264 | headers = xs_dict_append(headers, "x-creator", USER_AGENT); | 265 | headers = xs_dict_append(headers, "x-creator", USER_AGENT); |
| 265 | 266 | ||
| 267 | if (!xs_is_null(etag)) | ||
| 268 | headers = xs_dict_append(headers, "etag", etag); | ||
| 269 | |||
| 266 | if (b_size == 0 && body != NULL) | 270 | if (b_size == 0 && body != NULL) |
| 267 | b_size = strlen(body); | 271 | b_size = strlen(body); |
| 268 | 272 | ||
| @@ -137,7 +137,7 @@ int is_hidden(snac *snac, const char *id); | |||
| 137 | int actor_add(const char *actor, xs_dict *msg); | 137 | int actor_add(const char *actor, xs_dict *msg); |
| 138 | int actor_get(snac *snac, const char *actor, xs_dict **data); | 138 | int actor_get(snac *snac, const char *actor, xs_dict **data); |
| 139 | 139 | ||
| 140 | int static_get(snac *snac, const char *id, xs_val **data, int *size); | 140 | int static_get(snac *snac, const char *id, xs_val **data, int *size, const char *inm, xs_str **etag); |
| 141 | void static_put(snac *snac, const char *id, const char *data, int size); | 141 | void static_put(snac *snac, const char *id, const char *data, int size); |
| 142 | void static_put_meta(snac *snac, const char *id, const char *str); | 142 | void static_put_meta(snac *snac, const char *id, const char *str); |
| 143 | xs_str *static_get_meta(snac *snac, const char *id); | 143 | xs_str *static_get_meta(snac *snac, const char *id); |
| @@ -250,7 +250,7 @@ xs_str *not_really_markdown(const char *content, xs_list **attach); | |||
| 250 | xs_str *sanitize(const char *content); | 250 | xs_str *sanitize(const char *content); |
| 251 | 251 | ||
| 252 | int html_get_handler(const xs_dict *req, const char *q_path, | 252 | int html_get_handler(const xs_dict *req, const char *q_path, |
| 253 | char **body, int *b_size, char **ctype); | 253 | char **body, int *b_size, char **ctype, xs_str **etag); |
| 254 | int html_post_handler(const xs_dict *req, const char *q_path, | 254 | int html_post_handler(const xs_dict *req, const char *q_path, |
| 255 | char *payload, int p_size, | 255 | char *payload, int p_size, |
| 256 | char **body, int *b_size, char **ctype); | 256 | char **body, int *b_size, char **ctype); |