DoxigAlpha

sendHead

Sends HTTP headers without flushing.

Function parameters

Parameters

#
r:*Request

A Least-Recently-Used cache of open connections to be reused.

Types

#
ConnectionPool
A Least-Recently-Used cache of open connections to be reused.

Release all associated resources with the client.

Functions

#
deinit
Release all associated resources with the client.
initDefaultProxies
Populates `http_proxy` and `https_proxy` via standard proxy environment variables.
connectTcp
Reuses a `Connection` if one matching `host` and `port` is already open.
connectUnix
Connect to `path` as a unix domain socket.
connectProxied
Connect to `proxied_host:proxied_port` using the specified proxy with HTTP
connect
Connect to `host:port` using the specified protocol.
request
Open a connection to the host specified by `uri` and prepare to send a HTTP request.
fetch
Perform a one-shot HTTP request with the provided options.

Error sets in this namespace

Error Sets

#

= std.options.http_disable_tls

Values

#
disable_tls
= std.options.http_disable_tls

Source

Implementation

#
fn sendHead(r: *Request) Writer.Error!void {
    const uri = r.uri;
    const connection = r.connection.?;
    const w = connection.writer();

    try w.writeAll(@tagName(r.method));
    try w.writeByte(' ');

    if (r.method == .CONNECT) {
        try uri.writeToStream(w, .{ .authority = true });
    } else {
        try uri.writeToStream(w, .{
            .scheme = connection.proxied,
            .authentication = connection.proxied,
            .authority = connection.proxied,
            .path = true,
            .query = true,
        });
    }
    try w.writeByte(' ');
    try w.writeAll(@tagName(r.version));
    try w.writeAll("\r\n");

    if (try emitOverridableHeader("host: ", r.headers.host, w)) {
        try w.writeAll("host: ");
        try uri.writeToStream(w, .{ .authority = true });
        try w.writeAll("\r\n");
    }

    if (try emitOverridableHeader("authorization: ", r.headers.authorization, w)) {
        if (uri.user != null or uri.password != null) {
            try w.writeAll("authorization: ");
            try basic_authorization.write(uri, w);
            try w.writeAll("\r\n");
        }
    }

    if (try emitOverridableHeader("user-agent: ", r.headers.user_agent, w)) {
        try w.writeAll("user-agent: zig/");
        try w.writeAll(builtin.zig_version_string);
        try w.writeAll(" (std.http)\r\n");
    }

    if (try emitOverridableHeader("connection: ", r.headers.connection, w)) {
        if (r.keep_alive) {
            try w.writeAll("connection: keep-alive\r\n");
        } else {
            try w.writeAll("connection: close\r\n");
        }
    }

    if (try emitOverridableHeader("accept-encoding: ", r.headers.accept_encoding, w)) {
        try w.writeAll("accept-encoding: ");
        for (r.accept_encoding, 0..) |enabled, i| {
            if (!enabled) continue;
            const tag: http.ContentEncoding = @enumFromInt(i);
            if (tag == .identity) continue;
            const tag_name = @tagName(tag);
            try w.ensureUnusedCapacity(tag_name.len + 2);
            try w.writeAll(tag_name);
            try w.writeAll(", ");
        }
        w.undo(2);
        try w.writeAll("\r\n");
    }

    switch (r.transfer_encoding) {
        .chunked => try w.writeAll("transfer-encoding: chunked\r\n"),
        .content_length => |len| try w.print("content-length: {d}\r\n", .{len}),
        .none => {},
    }

    if (try emitOverridableHeader("content-type: ", r.headers.content_type, w)) {
        // The default is to omit content-type if not provided because
        // "application/octet-stream" is redundant.
    }

    for (r.extra_headers) |header| {
        assert(header.name.len != 0);

        try w.writeAll(header.name);
        try w.writeAll(": ");
        try w.writeAll(header.value);
        try w.writeAll("\r\n");
    }

    if (connection.proxied) proxy: {
        const proxy = switch (connection.protocol) {
            .plain => r.client.http_proxy,
            .tls => r.client.https_proxy,
        } orelse break :proxy;

        const authorization = proxy.authorization orelse break :proxy;
        try w.writeAll("proxy-authorization: ");
        try w.writeAll(authorization);
        try w.writeAll("\r\n");
    }

    try w.writeAll("\r\n");
}