For the issue #31135.
Below is a test example demonstrating how this PR is intended to be used
varthreaded:std.Io.Threaded=.init(arena_alloc.allocator(),.{.environ=init.minimal.environ});deferthreaded.deinit();constthread_io=threaded.io();constallocator=arena_alloc.allocator();varclient=std.http.Client{.allocator=arena_alloc.allocator(),.io=thread_io,};constunix_addr=("/Users/septemlee/.orbstack/run/docker.sock");consthost:std.Io.net.HostName=try.init("localhost");constconn=tryclient.connectUnix(host,unix_addr);varreq=tryclient.request(.GET,trystd.Uri.parse("http://localhost/v1.50/containers/json"),.{.connection=conn,});deferreq.deinit();constredirect_buf=tryallocator.alloc(u8,2048);deferallocator.free(redirect_buf);tryreq.sendBodiless();varrsp=tryreq.receiveHead(redirect_buf);constreader_buf=tryallocator.alloc(u8,2048);deferallocator.free(reader_buf);varreader=rsp.reader(reader_buf);constbody=tryreader.readAlloc(allocator,req.response_content_length.?);deferallocator.free(body);std.debug.print("{s}\n",.{body});
Output:
[{"Id":"f59b4ad80fe72cdf417d1b05d1930be6cce255c05375cd7bf3771ee4f9db89ca","Names":["/redis"],"Image":"4bea5ef8e69d","ImageID":"sha256:4bea5ef8e69dac80064fef357bc6b113c2d79f3cbccf3b0f8501045fc63bd596","Command":"docker-entrypoint.sh redis-server","Created":1769052743,"Ports":[{"IP":"0.0.0.0","PrivatePort":6379,"PublicPort":6379,"Type":"tcp"},{"IP":"::","PrivatePort":6379,"PublicPort":6379,"Type":"tcp"}],"Labels":{},"State":"running","Status":"Up 2 hours","HostConfig":{"NetworkMode":"bridge"},"NetworkSettings":{"Networks":{"bridge":{"IPAMConfig":null,"Links":null,"Aliases":null,"MacAddress":"a6:bc:60:60:fb:3b","DriverOpts":null,"GwPriority":0,"NetworkID":"674d7bf8063317298f983a8c202bbf67a638d1cd22d74f775d150bb2c9e6c24b","EndpointID":"7201ac6a0f3171e8efd6f1ffcbd667339b61aa52a80e21857b4235315344ed62","Gateway":"192.168.215.1","IPAddress":"192.168.215.2","IPPrefixLen":24,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"DNSNames":null}}},"Mounts":[{"Type":"volume","Name":"ea281b91a037a63cda2c362f4dcf31a2faa7eddd578d3b0a4b706686cf5f5414","Source":"","Destination":"/data","Driver":"local","Mode":"","RW":true,"Propagation":""}]}]
(削除)
# HostName equality check
/// Domain names are case-insensitive (RFC 5890, Section 2.3.2.4)pubfneql(a:HostName,b:HostName)bool{returnstd.ascii.eqlIgnoreCase(a.bytes,b.bytes);}
This behavior mainly affects findConnection.
If the comparison only checks host.bytes, then when multiple different Unix domain socket paths are involved, it seems possible that an existing connection could be reused unintentionally.
That said, the comment and RFC 5890 clearly scope this comparison to domain names. Since Unix domain sockets are not mentioned in the RFC, I wasn’t sure whether the intention is to keep this logic strictly domain-based, even for Unix connections.
(削除ここまで)(削除) I’m not sure whether adding Unix address–specific information into HostName is the correct or intended approach. I’d appreciate clarification on whether this aligns with the expected design.
(削除ここまで)
About std.http.Client.request
From reading the implementation, request internally calls connect, which currently handles connectTcp and connectProxied, but not connectUnix.
In the example above, I therefore pass the connection explicitly via RequestOptions.connection to ensure the Unix socket connection is used.
I’m not sure if this is the intended usage pattern (i.e. Unix connections are expected to be established and managed by the caller), or if support for connectUnix inside request is something that may be added later. I’d like to confirm the intended design here before going further.
For the issue #31135.
Below is a test example demonstrating how this PR is intended to be used
```zig
var threaded: std.Io.Threaded = .init(arena_alloc.allocator(), .{ .environ = init.minimal.environ });
defer threaded.deinit();
const thread_io = threaded.io();
const allocator = arena_alloc.allocator();
var client = std.http.Client{
.allocator = arena_alloc.allocator(),
.io = thread_io,
};
const unix_addr = ("/Users/septemlee/.orbstack/run/docker.sock");
const host: std.Io.net.HostName = try .init("localhost");
const conn = try client.connectUnix(host, unix_addr);
var req = try client.request(.GET, try std.Uri.parse("http://localhost/v1.50/containers/json"), .{
.connection = conn,
});
defer req.deinit();
const redirect_buf = try allocator.alloc(u8, 2048);
defer allocator.free(redirect_buf);
try req.sendBodiless();
var rsp = try req.receiveHead(redirect_buf);
const reader_buf = try allocator.alloc(u8, 2048);
defer allocator.free(reader_buf);
var reader = rsp.reader(reader_buf);
const body = try reader.readAlloc(allocator, req.response_content_length.?);
defer allocator.free(body);
std.debug.print("{s}\n", .{body});
```
Output:
```
[{"Id":"f59b4ad80fe72cdf417d1b05d1930be6cce255c05375cd7bf3771ee4f9db89ca","Names":["/redis"],"Image":"4bea5ef8e69d","ImageID":"sha256:4bea5ef8e69dac80064fef357bc6b113c2d79f3cbccf3b0f8501045fc63bd596","Command":"docker-entrypoint.sh redis-server","Created":1769052743,"Ports":[{"IP":"0.0.0.0","PrivatePort":6379,"PublicPort":6379,"Type":"tcp"},{"IP":"::","PrivatePort":6379,"PublicPort":6379,"Type":"tcp"}],"Labels":{},"State":"running","Status":"Up 2 hours","HostConfig":{"NetworkMode":"bridge"},"NetworkSettings":{"Networks":{"bridge":{"IPAMConfig":null,"Links":null,"Aliases":null,"MacAddress":"a6:bc:60:60:fb:3b","DriverOpts":null,"GwPriority":0,"NetworkID":"674d7bf8063317298f983a8c202bbf67a638d1cd22d74f775d150bb2c9e6c24b","EndpointID":"7201ac6a0f3171e8efd6f1ffcbd667339b61aa52a80e21857b4235315344ed62","Gateway":"192.168.215.1","IPAddress":"192.168.215.2","IPPrefixLen":24,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"DNSNames":null}}},"Mounts":[{"Type":"volume","Name":"ea281b91a037a63cda2c362f4dcf31a2faa7eddd578d3b0a4b706686cf5f5414","Source":"","Destination":"/data","Driver":"local","Mode":"","RW":true,"Propagation":""}]}]
```
<s>
# HostName equality check
```zig
/// Domain names are case-insensitive (RFC 5890, Section 2.3.2.4)
pub fn eql(a: HostName, b: HostName) bool {
return std.ascii.eqlIgnoreCase(a.bytes, b.bytes);
}
```
This behavior mainly affects `findConnection`.
If the comparison only checks `host.bytes`, then when multiple different Unix domain socket paths are involved, it seems possible that an existing connection could be reused unintentionally.
That said, the comment and RFC 5890 clearly scope this comparison to domain names. Since Unix domain sockets are not mentioned in the RFC, I wasn’t sure whether the intention is to keep this logic strictly domain-based, even for Unix connections.
I’m not sure whether adding Unix address–specific information into `HostName` is the correct or intended approach. I’d appreciate clarification on whether this aligns with the expected design.
</s>
# About `std.http.Client.request`
From reading the implementation, `request` internally calls `connect`, which currently handles `connectTcp` and `connectProxied`, but not `connectUnix`.
In the example above, I therefore pass the connection explicitly via `RequestOptions.connection` to ensure the Unix socket connection is used.
I’m not sure if this is the intended usage pattern (i.e. Unix connections are expected to be established and managed by the caller), or if support for `connectUnix` inside `request` is something that may be added later. I’d like to confirm the intended design here before going further.