Skip to content

Status codes and response headers

wired_http_handler fills a wired_http_exchange instead of just a body, so it can set the response status and add header fields. This page redirects, sets a cookie, and reads either an Authorization header or a cookie back to decide what to answer.

Code

main.c
#define WIRED_MAIN
#include "wired.h"
/* 1 if the request carries either the Bearer token or the session cookie
* a prior /login round would have handed out. */
static int authorized(const wired_h3reqdrive_req* req) {
wired_span v;
if (wired_http_req_header(req, wired_span_cstr("authorization"), &v) &&
wired_span_eq_cstr(v, "Bearer secret-token"))
return 1;
return wired_span_eq_cstr(
wired_span_of(req->cookie, req->cookie_len), "session=granted");
}
/* Three routes, one wired_http_handler each demonstrates: a 3xx with
* Location, a Set-Cookie, and an authorization check reading either the
* Authorization header or the cookie set by /login. */
static int on_request(void* ctx, wired_http_exchange* x) {
(void)ctx;
wired_span path = wired_h3req_path(x->req);
if (wired_span_eq_cstr(path, "/redirect")) {
x->status = 302;
wired_http_add_field(x, "location", "/target");
return 0;
}
if (wired_span_eq_cstr(path, "/login")) {
wired_http_add_field(x, "set-cookie", "session=granted");
return wired_http_reply_text(x, 200, "logged in");
}
if (wired_span_eq_cstr(path, "/secret"))
return authorized(x->req) ? wired_http_reply_text(x, 200, "top secret")
: wired_http_reply_text(x, 401, "unauthorized");
return wired_http_reply_text(x, 404, "not found");
}
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

Terminal window
$ ./h3-status-headers --port 4433
conn closed by peer (CONNECTION_CLOSE)
conn closed by peer (CONNECTION_CLOSE)
conn closed by peer (CONNECTION_CLOSE)
conn closed by peer (CONNECTION_CLOSE)
conn closed by peer (CONNECTION_CLOSE)
Terminal window
$ probe h3req 127.0.0.1:4433 GET /redirect
status 302
location: /target
Terminal window
$ probe h3req 127.0.0.1:4433 GET /login
status 200
content-type: text/plain
set-cookie: session=granted
logged in
Terminal window
$ probe h3req 127.0.0.1:4433 GET /secret
status 401
content-type: text/plain
unauthorized
Terminal window
$ probe h3req 127.0.0.1:4433 GET /secret -H Authorization: Bearer secret-token
status 200
content-type: text/plain
top secret
Terminal window
$ probe h3req 127.0.0.1:4433 GET /secret -H cookie: session=granted
status 200
content-type: text/plain
top secret
  • /redirect sets x->status = 302 and one x->fields[0] (location: /target), then returns 0 for an empty body.
  • /login sets a set-cookie field alongside a 200 body.
  • /secret calls wired_http_req_header(req, "authorization", &v) to read a regular header by name, and reads req->cookie / req->cookie_len directly — a dedicated field, not looked up through wired_http_req_header (see its doc comment).
  • x->fields holds up to WIRED_HTTP_MAX_FIELDS (8) entries; each is a wired_http_field (name, value), both lowercase on the wire (RFC 9114 4.2).
  • The probe client’s h3req -H 'name: value' sends one extra request header, and CheckRedirect is disabled so it prints the 302 itself instead of silently following it to /target.