Skip to content

Fix #2021 #2180

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
-------------------------------
Expand Down
6 changes: 5 additions & 1 deletion httplib.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
42 changes: 42 additions & 0 deletions test/test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down
Loading