use fmt; use io; use strings; // List of HTTP headers. export type header = [](str, str); // Adds a given HTTP header, which may be added more than once. The value is // duplicated, but the name is borrowed from the caller. The name should be // canonicalized by the caller. export fn add_header(head: *header, name: str, val: str) void = { append(head, (name, strings::dup(val))); }; // Sets the value of a given HTTP header, removing any previous values. The // value is duplicated, but the name is borrowed from the caller. The name // should be canonicalized by the caller. export fn set_header(head: *header, name: str, val: str) void = { del_header(head, name); add_header(head, name, val); }; // Removes an HTTP header from a list of [[header]]. If multiple headers match // the given name, all matching headers are removed. export fn del_header(head: *header, name: str) void = { for (let i = 0z; i < len(head); i += 1) { if (head[i].0 == name) { free(head[i].1); delete(head[i]); i -= 1; }; }; }; // Writes a list of HTTP headers to the provided I/O handle in the HTTP wire // format. export fn write_header(sink: io::handle, head: *header) (size | io::error) = { let z = 0z; for (let i = 0z; i < len(head); i += 1) { const (name, val) = head[i]; z += fmt::fprintf(sink, "{}: {}\r\n", name, val)?; }; return z; }; // Frees state associated with an HTTP [[header]]. export fn header_free(head: *header) void = { for (let i = 0z; i < len(head); i += 1) { free(head[i].1); }; free(*head); };