Skip to content

Http

Http fetches a URL over HTTP/1.1. It can block until the answer arrives, or run the request on its own thread and call you back, and it can be the transport behind url.fetch.

#import "Http.xc"

Http.get blocks the calling thread and returns an HttpResponse:

HttpResponse* r = Http.get(Url.withCString("http://example.com/"));
if (r.status() == (u32)200)
Stdio.printf("%s\n", r.bodyString().cString());
else if (r.status() == (u32)0)
Stdio.printf("no response: %s\n", r.error().cString());

Http.fetch runs the same request on a new thread and calls a block with the status and the body when it finishes:

Http.fetch(url, block void(u32 status, String* body) {
// runs on the request's thread, not the caller's
});

Http.install makes Http the transport behind url.fetch(…), so code written against Url works unchanged:

Http.install();
url.fetch(block void(u32 status, String* body) { … });

A status of 0 means there was no HTTP response at all — the host did not resolve, the connection was refused, or nothing arrived for 30 seconds. error says which. Any HTTP status, 404 and 500 included, is a response.

Each request uses its own connection and asks the server to close it. Redirects (301, 302, 303, 307 and 308) are followed, up to five. A chunked or Content-Length body is decoded.

Http does no cryptography itself. HttpTls.xc connects it to the optional TLS library, which verifies every server certificate against a CA bundle:

#import "HttpTls.xc"
if (!HttpTls.install())
Stdio.printf("no CA bundle found; https is off\n");

HttpTls.install looks for a bundle where macOS and the common Linux distributions keep one (/etc/ssl/cert.pem, /etc/ssl/certs/ca-certificates.crt, /etc/pki/tls/certs/ca-bundle.crt, /etc/ssl/ca-bundle.pem). Android and Windows keep their certificates elsewhere, so there, pass a PEM bundle to installWithBundle. There is no mode that skips the check. Without a TLS layer, an https URL fails with status 0 and an error saying so.

static HttpResponse* get(Url* url)

Sends a GET for url, following redirects, and returns the response. Blocks until the response has arrived or the request has failed.

static void fetch(Url* url, block cb void(u32, String*))

Runs get on a new thread and calls cb on that thread with the status and the body. On a failure the status is 0 and the body is 0.

static void install(void)

Sets the platform delegate to one whose fetch runs fetch, so url.fetch(…) uses this transport. It replaces any delegate already set.

static void deliverOn(RunLoop* loop)

Posts every completion (from fetch, and from url.fetch after install) to loop, so it runs on that loop’s thread. 0 goes back to running completions on the request’s own thread. Set it before starting requests.

static void setSecureLayer(HttpSecureLayer* layer)

Registers the layer https requests go through. HttpTls.install calls this; a program with its own TLS stack can adopt HttpSecureLayer and HttpSecureConnection and register that instead.

u32 status(void)

The HTTP status code, or 0 when there was no response.

String* error(void)

Why there was no response, or 0 when there was one.

Url* url(void)

The URL that answered, after any redirects.

Data* body(void)

The body’s bytes, empty when there were none.

String* bodyString(void)

The body as a string.

String* header(String* name)

A response header by name, in any case, or 0 when the server did not send it. A header sent more than once reads as its values joined by ", ".

Map* headers(void)

Every response header, keyed by its lower-case name.

static bool install(void)

Registers https with Http, verifying certificates against the first CA bundle found in the usual places. false when there is none, and https stays off.

static bool installWithBundle(String* path)

Registers https with Http, verifying certificates against the PEM bundle at path. false when the bundle cannot be loaded.