commit d783a1d22dc69dd0a2dcb0a4c53babe671f628b7
parent facc8b9d6c5d4547d5c496f988d4e3409e094c52
Author: Joris Vink <joris@coders.se>
Date: Mon, 26 Dec 2016 21:15:03 +0100
Add auto generated serving functions for assets.
These functions are created by the cli tool when building
and follow the naming format: asset_serve_<name>_<ext>().
Those serving functions can be used directly in handlers and
callthrough to a http_serveable() function that uses the SHA1
of the asset as its ETag and automatically checks for if-none-match.
Diffstat:
3 files changed, 41 insertions(+), 1 deletion(-)
diff --git a/includes/http.h b/includes/http.h
@@ -222,6 +222,8 @@ void http_request_wakeup(struct http_request *);
void http_process_request(struct http_request *);
ssize_t http_body_read(struct http_request *, void *, size_t);
void http_response(struct http_request *, int, const void *, size_t);
+void http_serveable(struct http_request *, const void *,
+ size_t, const char *);
void http_response_stream(struct http_request *, int, void *,
size_t, int (*cb)(struct netbuf *), void *);
int http_request_header(struct http_request *,
diff --git a/src/cli.c b/src/cli.c
@@ -187,6 +187,16 @@ static const char *gen_dirs[] = {
NULL
};
+static const char *http_serveable_function =
+ "int asset_serve_%s_%s(struct http_request *);\n\n"
+ "int\n"
+ "asset_serve_%s_%s(struct http_request *req)\n"
+ "{\n"
+ " http_serveable(req, asset_%s_%s, asset_len_%s_%s,\n"
+ " asset_sha1_%s_%s);\n"
+ " return (KORE_RESULT_OK);\n"
+ "}\n";
+
static const char *src_data =
"#include <kore/kore.h>\n"
"#include <kore/http.h>\n"
@@ -830,6 +840,8 @@ cli_build_asset(char *fpath, struct dirent *dp)
/* Start generating the file. */
cli_file_writef(out, "/* Auto generated */\n");
cli_file_writef(out, "#include <sys/types.h>\n\n");
+ cli_file_writef(out, "#include <kore/kore.h>\n");
+ cli_file_writef(out, "#include <kore/http.h>\n\n");
/* Write the file data as a byte array. */
cli_file_writef(out, "u_int8_t asset_%s_%s[] = {\n", name, ext);
@@ -862,8 +874,11 @@ cli_build_asset(char *fpath, struct dirent *dp)
name, ext, (u_int32_t)st.st_size);
cli_file_writef(out, "time_t asset_mtime_%s_%s = %" PRI_TIME_T ";\n",
name, ext, st.st_mtime);
- cli_file_writef(out, "const char *asset_sha1_%s_%s = \"%s\";\n",
+ cli_file_writef(out,
+ "const char *asset_sha1_%s_%s = \"\\\"%s\\\"\";\n",
name, ext, hash);
+ cli_file_writef(out, http_serveable_function, name, ext,
+ name, ext, name, ext, name, ext, name, ext);
/* Write the file symbols into assets.h so they can be used. */
cli_write_asset(name, ext);
diff --git a/src/http.c b/src/http.c
@@ -482,6 +482,29 @@ http_request_free(struct http_request *req)
}
void
+http_serveable(struct http_request *req, const void *data, size_t len,
+ const char *etag)
+{
+ char *match;
+
+ if (req->method != HTTP_METHOD_GET) {
+ http_response_header(req, "allow", "get");
+ http_response(req, HTTP_STATUS_BAD_REQUEST, NULL, 0);
+ return;
+ }
+
+ if (http_request_header(req, "if-none-match", &match)) {
+ if (!strcmp(match, etag)) {
+ http_response(req, HTTP_STATUS_NOT_MODIFIED, NULL, 0);
+ return;
+ }
+ }
+
+ http_response_header(req, "etag", etag);
+ http_response(req, HTTP_STATUS_OK, data, len);
+}
+
+void
http_response(struct http_request *req, int status, const void *d, size_t l)
{
kore_debug("http_response(%p, %d, %p, %zu)", req, status, d, l);