@@ -1995,9 +1995,9 @@ int getaddrinfo_with_timeout(const char *node, const char *service,
19951995 memcpy((*current)->ai_addr, sockaddr_ptr, sockaddr_len);
19961996
19971997 // Set port if service is specified
1998- if (service && strlen( service) > 0 ) {
1999- int port = atoi(service) ;
2000- if (port > 0 ) {
1998+ if (service && * service) {
1999+ int port = 0 ;
2000+ if (parse_port(service, strlen(service), port) ) {
20012001 if (sockaddr_ptr->sa_family == AF_INET) {
20022002 reinterpret_cast<struct sockaddr_in *>((*current)->ai_addr)
20032003 ->sin_port = htons(static_cast<uint16_t>(port));
@@ -3016,6 +3016,16 @@ bool read_headers(Stream &strm, Headers &headers) {
30163016 header_count++;
30173017 }
30183018
3019+ // RFC 9110 Section 8.6: Reject requests with multiple Content-Length
3020+ // headers that have different values to prevent request smuggling.
3021+ auto cl_range = headers.equal_range("Content-Length");
3022+ if (cl_range.first != cl_range.second) {
3023+ const auto &first_val = cl_range.first->second;
3024+ for (auto it = std::next(cl_range.first); it != cl_range.second; ++it) {
3025+ if (it->second != first_val) { return false; }
3026+ }
3027+ }
3028+
30193029 return true;
30203030}
30213031
@@ -7522,6 +7532,10 @@ bool Server::listen_internal() {
75227532 detail::set_socket_opt_time(sock, SOL_SOCKET, SO_SNDTIMEO,
75237533 write_timeout_sec_, write_timeout_usec_);
75247534
7535+ if (tcp_nodelay_) {
7536+ detail::set_socket_opt(sock, IPPROTO_TCP, TCP_NODELAY, 1);
7537+ }
7538+
75257539 if (!task_queue->enqueue(
75267540 [this, sock]() { process_and_close_socket(sock); })) {
75277541 output_error_log(Error::ResourceExhaustion, nullptr);
@@ -8911,7 +8925,7 @@ bool ClientImpl::redirect(Request &req, Response &res, Error &error) {
89118925
89128926 auto next_port = port_;
89138927 if (!port_str.empty()) {
8914- next_port = std::stoi (port_str);
8928+ if (!detail::parse_port (port_str, next_port)) { return false; }
89158929 } else if (!next_scheme.empty()) {
89168930 next_port = next_scheme == "https" ? 443 : 80;
89178931 }
@@ -8962,18 +8976,10 @@ bool ClientImpl::create_redirect_client(
89628976 // Setup basic client configuration first
89638977 setup_redirect_client(redirect_client);
89648978
8965- // SSL-specific configuration for proxy environments
8966- if (!proxy_host_.empty() && proxy_port_ != -1) {
8967- // Critical: Disable SSL verification for proxy environments
8968- redirect_client.enable_server_certificate_verification(false);
8969- redirect_client.enable_server_hostname_verification(false);
8970- } else {
8971- // For direct SSL connections, copy SSL verification settings
8972- redirect_client.enable_server_certificate_verification(
8973- server_certificate_verification_);
8974- redirect_client.enable_server_hostname_verification(
8975- server_hostname_verification_);
8976- }
8979+ redirect_client.enable_server_certificate_verification(
8980+ server_certificate_verification_);
8981+ redirect_client.enable_server_hostname_verification(
8982+ server_hostname_verification_);
89778983
89788984 // Transfer CA certificate to redirect client
89798985 if (!ca_cert_pem_.empty()) {
@@ -10690,7 +10696,8 @@ Client::Client(const std::string &scheme_host_port,
1069010696 if (host.empty()) { host = m[3].str(); }
1069110697
1069210698 auto port_str = m[4].str();
10693- auto port = !port_str.empty() ? std::stoi(port_str) : (is_ssl ? 443 : 80);
10699+ auto port = is_ssl ? 443 : 80;
10700+ if (!port_str.empty() && !detail::parse_port(port_str, port)) { return; }
1069410701
1069510702 if (is_ssl) {
1069610703#ifdef CPPHTTPLIB_SSL_ENABLED
@@ -16103,7 +16110,8 @@ WebSocketClient::WebSocketClient(
1610316110 if (host_.empty()) { host_ = m[3].str(); }
1610416111
1610516112 auto port_str = m[4].str();
16106- port_ = !port_str.empty() ? std::stoi(port_str) : (is_ssl ? 443 : 80);
16113+ port_ = is_ssl ? 443 : 80;
16114+ if (!port_str.empty() && !detail::parse_port(port_str, port_)) { return; }
1610716115
1610816116 path_ = m[5].str();
1610916117
0 commit comments