pub fn request(
client: *Client,
method: http.Method,
uri: Uri,
options: RequestOptions,
) RequestError!Request {
const io = client.io;
if (std.debug.runtime_safety) {
for (options.extra_headers) |header| {
assert(header.name.len != 0);
assert(std.mem.findScalar(u8, header.name, ':') == null);
assert(std.mem.findPosLinear(u8, header.name, 0, "\r\n") == null);
assert(std.mem.findPosLinear(u8, header.value, 0, "\r\n") == null);
}
for (options.privileged_headers) |header| {
assert(header.name.len != 0);
assert(std.mem.findPosLinear(u8, header.name, 0, "\r\n") == null);
assert(std.mem.findPosLinear(u8, header.value, 0, "\r\n") == null);
}
}
const protocol = Protocol.fromUri(uri) orelse return error.UnsupportedUriScheme;
if (protocol == .tls) tls: {
if (disable_tls) unreachable;
{
try client.ca_bundle_lock.lockShared(io);
defer client.ca_bundle_lock.unlockShared(io);
if (client.now != null) break :tls;
}
var bundle: std.crypto.Certificate.Bundle = .empty;
defer bundle.deinit(client.allocator);
const now = Io.Clock.real.now(io);
bundle.rescan(client.allocator, io, now) catch |err| switch (err) {
error.Canceled => |e| return e,
else => return error.CertificateBundleLoadFailure,
};
try client.ca_bundle_lock.lock(io);
defer client.ca_bundle_lock.unlock(io);
client.now = now;
std.mem.swap(std.crypto.Certificate.Bundle, &client.ca_bundle, &bundle);
}
const connection = options.connection orelse c: {
var host_name_buffer: [HostName.max_len]u8 = undefined;
const host_name = HostName.fromUri(uri, &host_name_buffer) catch |err| switch (err) {
error.UriMissingHost => |e| return e,
error.NameTooLong, error.InvalidHostName => return error.InvalidHostName,
};
break :c try client.connect(host_name, uriPort(uri, protocol), protocol);
};
return .{
.uri = uri,
.client = client,
.connection = connection,
.reader = .{
.in = connection.reader(),
.state = .ready,
// Populated when `http.Reader.bodyReader` is called.
.interface = undefined,
.max_head_len = client.read_buffer_size,
},
.keep_alive = options.keep_alive,
.method = method,
.version = options.version,
.transfer_encoding = .none,
.redirect_behavior = options.redirect_behavior,
.handle_continue = options.handle_continue,
.headers = options.headers,
.extra_headers = options.extra_headers,
.privileged_headers = options.privileged_headers,
};
}
Open a connection to the host specified by
uriand prepare to send a HTTP request.The caller is responsible for calling
deinit()on theRequest. This function is threadsafe.Asserts that "\r\n" does not occur in any header name or value.