diff --git a/README.md b/README.md index 75330a74..b607c205 100644 --- a/README.md +++ b/README.md @@ -1084,6 +1084,8 @@ cli.set_address_family(AF_UNIX); "my-socket.sock" can be a relative path or an absolute path. Your application must have the appropriate permissions for the path. You can also use an abstract socket address on Linux. To use an abstract socket address, prepend a null byte ('\x00') to the path. +This library automatically sets the Host header to "localhost" for Unix socket connections, similar to curl's behavior: + URI Encoding/Decoding Utilities ------------------------------- diff --git a/httplib.h b/httplib.h index 830c81e4..b1c778a0 100644 --- a/httplib.h +++ b/httplib.h @@ -8844,7 +8844,11 @@ inline bool ClientImpl::write_request(Stream &strm, Request &req, } if (!req.has_header("Host")) { - if (is_ssl()) { + // For Unix socket connections, use "localhost" as Host header (similar to + // curl behavior) + if (address_family_ == AF_UNIX) { + req.set_header("Host", "localhost"); + } else if (is_ssl()) { if (port_ == 443) { req.set_header("Host", host_); } else { diff --git a/test/test.cc b/test/test.cc index 7e397de3..f7624bf3 100644 --- a/test/test.cc +++ b/test/test.cc @@ -173,6 +173,48 @@ TEST_F(UnixSocketTest, abstract) { } #endif +TEST_F(UnixSocketTest, HostHeaderAutoSet) { + httplib::Server svr; + std::string received_host_header; + + svr.Get(pattern_, [&](const httplib::Request &req, httplib::Response &res) { + // Capture the Host header sent by the client + auto host_iter = req.headers.find("Host"); + if (host_iter != req.headers.end()) { + received_host_header = host_iter->second; + } + res.set_content(content_, "text/plain"); + }); + + std::thread t{[&] { + ASSERT_TRUE(svr.set_address_family(AF_UNIX).listen(pathname_, 80)); + }}; + auto se = detail::scope_exit([&] { + svr.stop(); + t.join(); + ASSERT_FALSE(svr.is_running()); + }); + + svr.wait_until_ready(); + ASSERT_TRUE(svr.is_running()); + + // Test that Host header is automatically set to "localhost" for Unix socket + // connections + httplib::Client cli{pathname_}; + cli.set_address_family(AF_UNIX); + ASSERT_TRUE(cli.is_valid()); + + const auto &result = cli.Get(pattern_); + ASSERT_TRUE(result) << "error: " << result.error(); + + const auto &resp = result.value(); + EXPECT_EQ(resp.status, StatusCode::OK_200); + EXPECT_EQ(resp.body, content_); + + // Verify that Host header was automatically set to "localhost" + EXPECT_EQ(received_host_header, "localhost"); +} + #ifndef _WIN32 TEST(SocketStream, wait_writable_UNIX) { int fds[2];