静的ファイルを配信する
wired_staticfile_resolve は、リクエストパスをドキュメントルート下のファイルパスに変換し、パストラバーサル(.. を使ってドキュメントルートの外へ抜け出す攻撃)を拒否します。
wired_mimetype_for_path は、その拡張子から Content-Type を選びます。
このページのサーバーは、この例のディレクトリに置いた 2 つのファイルを配信し、それ以外のパスには 404 を返します。
コード
#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;}実行結果
$ ./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"wired_staticfile_resolve(".", reqpath, "index.html", resolved, cap)は、 リクエストパスを現在のディレクトリ下に解決し、..を含むセグメントを拒否します。wired_mimetype_for_path(resolved)は、解決済みパスの拡張子を読みます (.txtはtext/plain、.htmlはtext/html)。 この呼び出しは最初のラウンド(ハンドラーが呼ばれる 1 回分の処理)で一度だけ行い、wired_h3reqdrive自身の content-type フィールドと同じ扱いにします。wired_fio_open/wired_fio_size/wired_fio_pread/wired_fio_closeは、x->body->cap単位でファイルをチャンク読みします。word_listの例が、1 ラウンドより大きいドキュメントルートで使っているのと同じ読み方です。- ファイルが見つからない場合、または
wired_staticfile_resolveが拒否した場合は、x->status(wired_http_handler、パスによる振り分け ページで直した仕組みと同じ)で本物の 404 を返します。