Serving static files
wired_staticfile_resolve turns a request path into a file under a document
root, rejecting path traversal, and wired_mimetype_for_path picks the
Content-Type from its extension. This page serves two files committed next
to the snippet and answers 404 for anything else.
Code
#define WIRED_MAIN#include "wired.h"
/* The whole point of this page: wired_staticfile_resolve rejects path * traversal and picks an index file for a directory request, then * wired_mimetype_for_path infers the Content-Type from the resolved * file's extension. */
/* Serve one round of the resolved file's bytes at x->offset, 404 if it * does not resolve or open/read. */static int on_request(void* ctx, wired_http_exchange* x) { char resolved[256], reqpath[128]; ssz fd, total, got; (void)ctx; wired_span_to_cstr(reqpath, sizeof reqpath, wired_h3req_path(x->req)); if (!wired_staticfile_resolve( ".", reqpath, "index.html", resolved, sizeof resolved)) return wired_http_reply_text(x, 404, "not found"); fd = wired_fio_open(resolved); if (fd < 0) return wired_http_reply_text(x, 404, "not found"); total = wired_fio_size(resolved); got = wired_fio_pread(fd, wired_mspan_of(x->body->p, x->body->cap), x->offset); wired_fio_close(fd); if (total < 0 || got < 0) return wired_http_reply_text(x, 404, "not found"); if (x->offset == 0) { x->content_type = wired_mimetype_for_path(resolved); x->total_size = (u64)total; } x->body->len = (usz)got; if (x->offset + (u64)got < (u64)total) x->more = 1; return 1;}
int wired_main(int argc, char** argv) { /* Fixed demo identity (self-signed certificate; never for production). */ static wired_srvboot_demo_keys keys; wired_srvboot_id id; wired_srvboot_demo(&id, &keys, 0x50, "guide-h3");
u16 port = (u16)wired_cliargs_int(argc, argv, "--port", 4433); wired_srvrun_handler h = {.http = on_request}; wired_srvrun_obs obs = {0}; return wired_server_run(port, &id, h, obs) ? 0 : 1;}Output
$ ./h3-static-files --port 4433conn closed by peer (CONNECTION_CLOSE)$ probe h3get 127.0.0.1:4433 /hello.txt /page.html /nope.txtGET /hello.txt status=200 content-type=text/plain body="hello static file"GET /page.html status=200 content-type=text/html body="<h1>hi</h1>"GET /nope.txt status=404 content-type=text/plain body="not found"How it works
Section titled “How it works”wired_staticfile_resolve(".", reqpath, "index.html", resolved, cap)resolves the request path under the current directory, rejecting any..segment.wired_mimetype_for_path(resolved)reads the resolved path’s extension (.txt→text/plain,.html→text/html), set once on the first round, likewired_h3reqdrive’s own content-type field.wired_fio_open/wired_fio_size/wired_fio_pread/wired_fio_closestream the file in chunks ofx->body->cap, the same chunked read theword_listexample uses for a document root larger than one round.- A missing file, or one
wired_staticfile_resolverejects, answers a real 404 viax->status(wired_http_handler, like the fix on the routing page).