summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data.c39
-rw-r--r--html.c10
-rw-r--r--httpd.c6
-rw-r--r--snac.h4
4 files changed, 45 insertions, 14 deletions
diff --git a/data.c b/data.c
index 117e16f..87cfc98 100644
--- a/data.c
+++ b/data.c
@@ -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;
diff --git a/html.c b/html.c
index 7a0c805..425df4b 100644
--- a/html.c
+++ b/html.c
@@ -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
diff --git a/httpd.c b/httpd.c
index de70089..9aac3b5 100644
--- a/httpd.c
+++ b/httpd.c
@@ -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);
diff --git a/snac.h b/snac.h
index 13cfe8c..74f4969 100644
--- a/snac.h
+++ b/snac.h
@@ -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);