|
|
@@ -1052,6 +1052,9 @@ private:
|
|
|
|
|
|
ssize_t write_headers(Stream &strm, const Headers &headers);
|
|
|
|
|
|
+std::string make_host_and_port_string(const std::string &host, int port,
|
|
|
+ bool is_ssl);
|
|
|
+
|
|
|
} // namespace detail
|
|
|
|
|
|
class Server {
|
|
|
@@ -1719,8 +1722,6 @@ private:
|
|
|
const std::string &boundary, const UploadFormDataItems &items,
|
|
|
const FormDataProviderItems &provider_items) const;
|
|
|
|
|
|
- std::string adjust_host_string(const std::string &host) const;
|
|
|
-
|
|
|
virtual bool
|
|
|
process_socket(const Socket &socket,
|
|
|
std::chrono::time_point<std::chrono::steady_clock> start_time,
|
|
|
@@ -7261,6 +7262,30 @@ inline bool RegexMatcher::match(Request &request) const {
|
|
|
return std::regex_match(request.path, request.matches, regex_);
|
|
|
}
|
|
|
|
|
|
+inline std::string make_host_and_port_string(const std::string &host, int port,
|
|
|
+ bool is_ssl) {
|
|
|
+ std::string result;
|
|
|
+
|
|
|
+ // Enclose IPv6 address in brackets (but not if already enclosed)
|
|
|
+ if (host.find(':') == std::string::npos ||
|
|
|
+ (!host.empty() && host[0] == '[')) {
|
|
|
+ // IPv4, hostname, or already bracketed IPv6
|
|
|
+ result = host;
|
|
|
+ } else {
|
|
|
+ // IPv6 address without brackets
|
|
|
+ result = "[" + host + "]";
|
|
|
+ }
|
|
|
+
|
|
|
+ // Append port if not default
|
|
|
+ if ((!is_ssl && port == 80) || (is_ssl && port == 443)) {
|
|
|
+ ; // do nothing
|
|
|
+ } else {
|
|
|
+ result += ":" + std::to_string(port);
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
} // namespace detail
|
|
|
|
|
|
// HTTP server implementation
|
|
|
@@ -8522,7 +8547,7 @@ inline ClientImpl::ClientImpl(const std::string &host, int port,
|
|
|
const std::string &client_cert_path,
|
|
|
const std::string &client_key_path)
|
|
|
: host_(detail::escape_abstract_namespace_unix_domain(host)), port_(port),
|
|
|
- host_and_port_(adjust_host_string(host_) + ":" + std::to_string(port)),
|
|
|
+ host_and_port_(detail::make_host_and_port_string(host_, port, is_ssl())),
|
|
|
client_cert_path_(client_cert_path), client_key_path_(client_key_path) {}
|
|
|
|
|
|
inline ClientImpl::~ClientImpl() {
|
|
|
@@ -8703,8 +8728,9 @@ inline bool ClientImpl::send_(Request &req, Response &res, Error &error) {
|
|
|
{
|
|
|
std::lock_guard<std::mutex> guard(socket_mutex_);
|
|
|
|
|
|
- // Set this to false immediately - if it ever gets set to true by the end of
|
|
|
- // the request, we know another thread instructed us to close the socket.
|
|
|
+ // Set this to false immediately - if it ever gets set to true by the end
|
|
|
+ // of the request, we know another thread instructed us to close the
|
|
|
+ // socket.
|
|
|
socket_should_be_closed_when_request_is_done_ = false;
|
|
|
|
|
|
auto is_alive = false;
|
|
|
@@ -8720,10 +8746,10 @@ inline bool ClientImpl::send_(Request &req, Response &res, Error &error) {
|
|
|
#endif
|
|
|
|
|
|
if (!is_alive) {
|
|
|
- // Attempt to avoid sigpipe by shutting down non-gracefully if it seems
|
|
|
- // like the other side has already closed the connection Also, there
|
|
|
- // cannot be any requests in flight from other threads since we locked
|
|
|
- // request_mutex_, so safe to close everything immediately
|
|
|
+ // Attempt to avoid sigpipe by shutting down non-gracefully if it
|
|
|
+ // seems like the other side has already closed the connection Also,
|
|
|
+ // there cannot be any requests in flight from other threads since we
|
|
|
+ // locked request_mutex_, so safe to close everything immediately
|
|
|
const bool shutdown_gracefully = false;
|
|
|
shutdown_ssl(socket_, shutdown_gracefully);
|
|
|
shutdown_socket(socket_);
|
|
|
@@ -9027,7 +9053,8 @@ inline bool ClientImpl::create_redirect_client(
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// New method for robust client setup (based on basic_manual_redirect.cpp logic)
|
|
|
+// New method for robust client setup (based on basic_manual_redirect.cpp
|
|
|
+// logic)
|
|
|
template <typename ClientType>
|
|
|
inline void ClientImpl::setup_redirect_client(ClientType &client) {
|
|
|
// Copy basic settings first
|
|
|
@@ -9131,18 +9158,8 @@ inline bool ClientImpl::write_request(Stream &strm, Request &req,
|
|
|
// 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 {
|
|
|
- req.set_header("Host", host_and_port_);
|
|
|
- }
|
|
|
} else {
|
|
|
- if (port_ == 80) {
|
|
|
- req.set_header("Host", host_);
|
|
|
- } else {
|
|
|
- req.set_header("Host", host_and_port_);
|
|
|
- }
|
|
|
+ req.set_header("Host", host_and_port_);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -9409,12 +9426,6 @@ inline Result ClientImpl::send_with_content_provider(
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
-inline std::string
|
|
|
-ClientImpl::adjust_host_string(const std::string &host) const {
|
|
|
- if (host.find(':') != std::string::npos) { return "[" + host + "]"; }
|
|
|
- return host;
|
|
|
-}
|
|
|
-
|
|
|
inline void ClientImpl::output_log(const Request &req,
|
|
|
const Response &res) const {
|
|
|
if (logger_) {
|
|
|
@@ -9538,8 +9549,8 @@ inline ContentProviderWithoutLength ClientImpl::get_multipart_content_provider(
|
|
|
const FormDataProviderItems &provider_items) const {
|
|
|
size_t cur_item = 0;
|
|
|
size_t cur_start = 0;
|
|
|
- // cur_item and cur_start are copied to within the std::function and maintain
|
|
|
- // state between successive calls
|
|
|
+ // cur_item and cur_start are copied to within the std::function and
|
|
|
+ // maintain state between successive calls
|
|
|
return [&, cur_item, cur_start](size_t offset,
|
|
|
DataSink &sink) mutable -> bool {
|
|
|
if (!offset && !items.empty()) {
|
|
|
@@ -10251,8 +10262,8 @@ inline void ClientImpl::stop() {
|
|
|
// If there is anything ongoing right now, the ONLY thread-safe thing we can
|
|
|
// do is to shutdown_socket, so that threads using this socket suddenly
|
|
|
// discover they can't read/write any more and error out. Everything else
|
|
|
- // (closing the socket, shutting ssl down) is unsafe because these actions are
|
|
|
- // not thread-safe.
|
|
|
+ // (closing the socket, shutting ssl down) is unsafe because these actions
|
|
|
+ // are not thread-safe.
|
|
|
if (socket_requests_in_flight_ > 0) {
|
|
|
shutdown_socket(socket_);
|
|
|
|
|
|
@@ -10889,7 +10900,8 @@ inline void SSLClient::set_ca_cert_store(X509_STORE *ca_cert_store) {
|
|
|
if (ca_cert_store) {
|
|
|
if (ctx_) {
|
|
|
if (SSL_CTX_get_cert_store(ctx_) != ca_cert_store) {
|
|
|
- // Free memory allocated for old cert and use new store `ca_cert_store`
|
|
|
+ // Free memory allocated for old cert and use new store
|
|
|
+ // `ca_cert_store`
|
|
|
SSL_CTX_set_cert_store(ctx_, ca_cert_store);
|
|
|
ca_cert_store_ = ca_cert_store;
|
|
|
}
|
|
|
@@ -10914,7 +10926,8 @@ inline bool SSLClient::create_and_connect_socket(Socket &socket, Error &error) {
|
|
|
return is_valid() && ClientImpl::create_and_connect_socket(socket, error);
|
|
|
}
|
|
|
|
|
|
-// Assumes that socket_mutex_ is locked and that there are no requests in flight
|
|
|
+// Assumes that socket_mutex_ is locked and that there are no requests in
|
|
|
+// flight
|
|
|
inline bool SSLClient::connect_with_proxy(
|
|
|
Socket &socket,
|
|
|
std::chrono::time_point<std::chrono::steady_clock> start_time,
|