commit d343b40
default
·
2023-07-02 09:11:01 +0000 UTC
parent b5495ab
Added HTTP caching to static data.
M
data.c
+32,
-7
1@@ -1533,19 +1533,44 @@ xs_str *_static_fn(snac *snac, const char *id)
2 }
3
4
5-int static_get(snac *snac, const char *id, xs_val **data, int *size)
6+int static_get(snac *snac, const char *id, xs_val **data, int *size,
7+ const char *inm, xs_str **etag)
8 /* returns static content */
9 {
10 xs *fn = _static_fn(snac, id);
11- FILE *f;
12 int status = 404;
13
14- if (fn && (f = fopen(fn, "rb")) != NULL) {
15- *size = XS_ALL;
16- *data = xs_read(f, size);
17- fclose(f);
18+ if (fn) {
19+ double tm = mtime(fn);
20
21- status = 200;
22+ if (tm > 0.0) {
23+ /* file exists; build the etag */
24+ xs *e = xs_fmt("W/\"snac-%.0lf\"", tm);
25+
26+ /* if if-none-match is set, check if it's the same */
27+ if (!xs_is_null(inm) && strcmp(e, inm) == 0) {
28+ /* client has the newest version */
29+ status = 304;
30+ }
31+ else {
32+ /* newer or never downloaded; read the full file */
33+ FILE *f;
34+
35+ if ((f = fopen(fn, "rb")) != NULL) {
36+ *size = XS_ALL;
37+ *data = xs_read(f, size);
38+ fclose(f);
39+
40+ status = 200;
41+ }
42+ }
43+
44+ /* if caller wants the etag, return it */
45+ if (etag != NULL)
46+ *etag = xs_dup(e);
47+
48+ srv_debug(1, xs_fmt("static_get(): %d %s %s", status, id, e));
49+ }
50 }
51
52 return status;
M
html.c
+6,
-4
1@@ -226,7 +226,7 @@ d_char *html_user_header(snac *snac, d_char *s, int local)
2 int size;
3
4 /* try to open the user css */
5- if (!valid_status(static_get(snac, "style.css", &css, &size))) {
6+ if (!valid_status(static_get(snac, "style.css", &css, &size, NULL, NULL))) {
7 /* it's not there; try to open the server-wide css */
8 FILE *f;
9 xs *g_css_fn = xs_fmt("%s/style.css", srv_basedir);
10@@ -1542,7 +1542,7 @@ xs_str *html_notifications(snac *snac)
11
12
13 int html_get_handler(const xs_dict *req, const char *q_path,
14- char **body, int *b_size, char **ctype)
15+ char **body, int *b_size, char **ctype, xs_str **etag)
16 {
17 char *accept = xs_dict_get(req, "accept");
18 int status = 404;
19@@ -1695,10 +1695,12 @@ int html_get_handler(const xs_dict *req, const char *q_path,
20 char *id = xs_list_get(l, 1);
21 int sz;
22
23- if (valid_status(static_get(&snac, id, body, &sz))) {
24+ status = static_get(&snac, id, body, &sz,
25+ xs_dict_get(req, "if-none-match"), etag);
26+
27+ if (valid_status(status)) {
28 *b_size = sz;
29 *ctype = xs_mime_by_ext(id);
30- status = 200;
31 }
32 }
33 else
M
httpd.c
+5,
-1
1@@ -156,6 +156,7 @@ void httpd_connection(FILE *f)
2 xs *headers = NULL;
3 xs *q_path = NULL;
4 xs *payload = NULL;
5+ xs *etag = NULL;
6 int p_size = 0;
7 char *p;
8
9@@ -198,7 +199,7 @@ void httpd_connection(FILE *f)
10 #endif /* NO_MASTODON_API */
11
12 if (status == 0)
13- status = html_get_handler(req, q_path, &body, &b_size, &ctype);
14+ status = html_get_handler(req, q_path, &body, &b_size, &ctype, &etag);
15 }
16 else
17 if (strcmp(method, "POST") == 0) {
18@@ -263,6 +264,9 @@ void httpd_connection(FILE *f)
19 headers = xs_dict_append(headers, "content-type", ctype);
20 headers = xs_dict_append(headers, "x-creator", USER_AGENT);
21
22+ if (!xs_is_null(etag))
23+ headers = xs_dict_append(headers, "etag", etag);
24+
25 if (b_size == 0 && body != NULL)
26 b_size = strlen(body);
27
M
snac.h
+2,
-2
1@@ -137,7 +137,7 @@ int is_hidden(snac *snac, const char *id);
2 int actor_add(const char *actor, xs_dict *msg);
3 int actor_get(snac *snac, const char *actor, xs_dict **data);
4
5-int static_get(snac *snac, const char *id, xs_val **data, int *size);
6+int static_get(snac *snac, const char *id, xs_val **data, int *size, const char *inm, xs_str **etag);
7 void static_put(snac *snac, const char *id, const char *data, int size);
8 void static_put_meta(snac *snac, const char *id, const char *str);
9 xs_str *static_get_meta(snac *snac, const char *id);
10@@ -250,7 +250,7 @@ xs_str *not_really_markdown(const char *content, xs_list **attach);
11 xs_str *sanitize(const char *content);
12
13 int html_get_handler(const xs_dict *req, const char *q_path,
14- char **body, int *b_size, char **ctype);
15+ char **body, int *b_size, char **ctype, xs_str **etag);
16 int html_post_handler(const xs_dict *req, const char *q_path,
17 char *payload, int p_size,
18 char **body, int *b_size, char **ctype);