diff --git a/README.md b/README.md index 75330a7477..b607c205a6 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 830c81e42a..b1c778a058 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 7e397de322..f7624bf365 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];