DoxigAlpha

connectProxied

Connect to proxied_host:proxied_port using the specified proxy with HTTP CONNECT. This will reuse a connection if one is already open.

This function is threadsafe.

Function parameters

Parameters

#
client:*Client
proxy:*Proxy
proxied_host:[]const u8
proxied_port:u16

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

#
pub fn connectProxied(
    client: *Client,
    proxy: *Proxy,
    proxied_host: []const u8,
    proxied_port: u16,
) !*Connection {
    if (!proxy.supports_connect) return error.TunnelNotSupported;

    if (client.connection_pool.findConnection(.{
        .host = proxied_host,
        .port = proxied_port,
        .protocol = proxy.protocol,
    })) |node| return node;

    var maybe_valid = false;
    (tunnel: {
        const connection = try client.connectTcpOptions(.{
            .host = proxy.host,
            .port = proxy.port,
            .protocol = proxy.protocol,
            .proxied_host = proxied_host,
            .proxied_port = proxied_port,
        });
        errdefer {
            connection.closing = true;
            client.connection_pool.release(connection);
        }

        var req = client.request(.CONNECT, .{
            .scheme = "http",
            .host = .{ .raw = proxied_host },
            .port = proxied_port,
        }, .{
            .redirect_behavior = .unhandled,
            .connection = connection,
        }) catch |err| {
            break :tunnel err;
        };
        defer req.deinit();

        req.sendBodiless() catch |err| break :tunnel err;
        const response = req.receiveHead(&.{}) catch |err| break :tunnel err;

        if (response.head.status.class() == .server_error) {
            maybe_valid = true;
            break :tunnel error.ServerError;
        }

        if (response.head.status != .ok) break :tunnel error.ConnectionRefused;

        // this connection is now a tunnel, so we can't use it for anything
        // else, it will only be released when the client is de-initialized.
        req.connection = null;

        connection.closing = false;

        return connection;
    }) catch {
        // something went wrong with the tunnel
        proxy.supports_connect = maybe_valid;
        return error.TunnelNotSupported;
    };
}