1
Fork 0

Initial commit

This commit is contained in:
Drew DeVault 2023-02-09 20:54:21 +01:00
parent ea1a5ceb8d
commit a0bfaef6ba
4 changed files with 91 additions and 0 deletions

21
cmd/http/main.ha Normal file
View file

@ -0,0 +1,21 @@
use net::http;
use net::ip;
use net::uri;
use os;
export fn main() void = {
const req = &http::request {
method = http::GET,
target = &uri::uri {
scheme = "http",
host = ip::LOCAL_V6,
path = "/",
...
},
body = void,
...
};
http::add_header(&req.header, "User-Agent", "Hare test client");
http::add_header(&req.header, "Content-Length", "100");
http::write_header(os::stdout, &req.header)!;
};

8
net/http/README Normal file
View file

@ -0,0 +1,8 @@
TODO: Flesh me out
Caveats:
- No attempt is made to validate that the input for client requests or responses
are valid according to the HTTP grammar; such cases will fail when rejected by
the other party.
- Details indicated by RFC 7230 et al as "obsolete" are not implemented

42
net/http/header.ha Normal file
View file

@ -0,0 +1,42 @@
use io;
use fmt;
// List of HTTP headers.
export type header = [](str, str);
// Adds a given HTTP header, which may be added more than once. The provided
// name and value are borrowed from the caller. The provided header name should
// be canonicalized by the caller.
export fn add_header(head: *header, name: str, val: str) void = {
append(head, (name, val));
};
// Sets the value of a given HTTP header, removing any previous values. The
// provided name and value are borrowed from the caller. The provided header
// 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) {
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;
};

View file

@ -0,0 +1,20 @@
use io;
use net::uri;
// Stores state related to an HTTP request.
export type request = struct {
// HTTP request method, e.g. GET
method: str,
// Request target URI.
//
// Note that the normal constraints for [[uri::parse]] are not upheld in
// the case of a request using the origin-form (e.g. /index.html), i.e.
// the scheme field may be empty.
target: *uri::uri,
// List of HTTP request headers.
header: header,
// I/O reader for the request body.
body: (io::handle | void),
};