diff options
author | default <nobody@localhost> | 2023-07-02 11:11:01 +0200 |
---|---|---|
committer | default <nobody@localhost> | 2023-07-02 11:11:01 +0200 |
commit | d343b40ee553de8d98c18d3547e6c9b12ab96b48 (patch) | |
tree | 2f2d9ab495d2ad4e8187f31530d8019968b905bf | |
parent | b5495ab40b960864e46d55ad28255664e0f4eb73 (diff) |
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) } -int static_get(snac *snac, const char *id, xs_val **data, int *size) +int static_get(snac *snac, const char *id, xs_val **data, int *size, + const char *inm, xs_str **etag) /* returns static content */ { xs *fn = _static_fn(snac, id); - FILE *f; int status = 404; - if (fn && (f = fopen(fn, "rb")) != NULL) { - *size = XS_ALL; - *data = xs_read(f, size); - fclose(f); + if (fn) { + double tm = mtime(fn); - status = 200; + if (tm > 0.0) { + /* file exists; build the etag */ + xs *e = xs_fmt("W/\"snac-%.0lf\"", tm); + + /* if if-none-match is set, check if it's the same */ + if (!xs_is_null(inm) && strcmp(e, inm) == 0) { + /* client has the newest version */ + status = 304; + } + else { + /* newer or never downloaded; read the full file */ + FILE *f; + + if ((f = fopen(fn, "rb")) != NULL) { + *size = XS_ALL; + *data = xs_read(f, size); + fclose(f); + + status = 200; + } + } + + /* if caller wants the etag, return it */ + if (etag != NULL) + *etag = xs_dup(e); + + srv_debug(1, xs_fmt("static_get(): %d %s %s", status, id, e)); + } } return status; @@ -226,7 +226,7 @@ d_char *html_user_header(snac *snac, d_char *s, int local) int size; /* try to open the user css */ - if (!valid_status(static_get(snac, "style.css", &css, &size))) { + if (!valid_status(static_get(snac, "style.css", &css, &size, NULL, NULL))) { /* it's not there; try to open the server-wide css */ FILE *f; xs *g_css_fn = xs_fmt("%s/style.css", srv_basedir); @@ -1542,7 +1542,7 @@ xs_str *html_notifications(snac *snac) int html_get_handler(const xs_dict *req, const char *q_path, - char **body, int *b_size, char **ctype) + char **body, int *b_size, char **ctype, xs_str **etag) { char *accept = xs_dict_get(req, "accept"); int status = 404; @@ -1695,10 +1695,12 @@ int html_get_handler(const xs_dict *req, const char *q_path, char *id = xs_list_get(l, 1); int sz; - if (valid_status(static_get(&snac, id, body, &sz))) { + status = static_get(&snac, id, body, &sz, + xs_dict_get(req, "if-none-match"), etag); + + if (valid_status(status)) { *b_size = sz; *ctype = xs_mime_by_ext(id); - status = 200; } } else @@ -156,6 +156,7 @@ void httpd_connection(FILE *f) xs *headers = NULL; xs *q_path = NULL; xs *payload = NULL; + xs *etag = NULL; int p_size = 0; char *p; @@ -198,7 +199,7 @@ void httpd_connection(FILE *f) #endif /* NO_MASTODON_API */ if (status == 0) - status = html_get_handler(req, q_path, &body, &b_size, &ctype); + status = html_get_handler(req, q_path, &body, &b_size, &ctype, &etag); } else if (strcmp(method, "POST") == 0) { @@ -263,6 +264,9 @@ void httpd_connection(FILE *f) headers = xs_dict_append(headers, "content-type", ctype); headers = xs_dict_append(headers, "x-creator", USER_AGENT); + if (!xs_is_null(etag)) + headers = xs_dict_append(headers, "etag", etag); + if (b_size == 0 && body != NULL) b_size = strlen(body); @@ -137,7 +137,7 @@ int is_hidden(snac *snac, const char *id); int actor_add(const char *actor, xs_dict *msg); int actor_get(snac *snac, const char *actor, xs_dict **data); -int static_get(snac *snac, const char *id, xs_val **data, int *size); +int static_get(snac *snac, const char *id, xs_val **data, int *size, const char *inm, xs_str **etag); void static_put(snac *snac, const char *id, const char *data, int size); void static_put_meta(snac *snac, const char *id, const char *str); 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); xs_str *sanitize(const char *content); int html_get_handler(const xs_dict *req, const char *q_path, - char **body, int *b_size, char **ctype); + char **body, int *b_size, char **ctype, xs_str **etag); int html_post_handler(const xs_dict *req, const char *q_path, char *payload, int p_size, char **body, int *b_size, char **ctype); |