memcpy((*current)->ai_addr, sockaddr_ptr, sockaddr_len);
// Set port if service is specified
- if (service && strlen(service) > 0) {
- int port = atoi(service);
- if (port > 0) {
+ if (service && *service) {
+ int port = 0;
+ if (parse_port(service, strlen(service), port)) {
if (sockaddr_ptr->sa_family == AF_INET) {
reinterpret_cast<struct sockaddr_in *>((*current)->ai_addr)
->sin_port = htons(static_cast<uint16_t>(port));
header_count++;
}
+ // RFC 9110 Section 8.6: Reject requests with multiple Content-Length
+ // headers that have different values to prevent request smuggling.
+ auto cl_range = headers.equal_range("Content-Length");
+ if (cl_range.first != cl_range.second) {
+ const auto &first_val = cl_range.first->second;
+ for (auto it = std::next(cl_range.first); it != cl_range.second; ++it) {
+ if (it->second != first_val) { return false; }
+ }
+ }
+
return true;
}
detail::set_socket_opt_time(sock, SOL_SOCKET, SO_SNDTIMEO,
write_timeout_sec_, write_timeout_usec_);
+ if (tcp_nodelay_) {
+ detail::set_socket_opt(sock, IPPROTO_TCP, TCP_NODELAY, 1);
+ }
+
if (!task_queue->enqueue(
[this, sock]() { process_and_close_socket(sock); })) {
output_error_log(Error::ResourceExhaustion, nullptr);
auto next_port = port_;
if (!port_str.empty()) {
- next_port = std::stoi(port_str);
+ if (!detail::parse_port(port_str, next_port)) { return false; }
} else if (!next_scheme.empty()) {
next_port = next_scheme == "https" ? 443 : 80;
}
// Setup basic client configuration first
setup_redirect_client(redirect_client);
- // SSL-specific configuration for proxy environments
- if (!proxy_host_.empty() && proxy_port_ != -1) {
- // Critical: Disable SSL verification for proxy environments
- redirect_client.enable_server_certificate_verification(false);
- redirect_client.enable_server_hostname_verification(false);
- } else {
- // For direct SSL connections, copy SSL verification settings
- redirect_client.enable_server_certificate_verification(
- server_certificate_verification_);
- redirect_client.enable_server_hostname_verification(
- server_hostname_verification_);
- }
+ redirect_client.enable_server_certificate_verification(
+ server_certificate_verification_);
+ redirect_client.enable_server_hostname_verification(
+ server_hostname_verification_);
// Transfer CA certificate to redirect client
if (!ca_cert_pem_.empty()) {
if (host.empty()) { host = m[3].str(); }
auto port_str = m[4].str();
- auto port = !port_str.empty() ? std::stoi(port_str) : (is_ssl ? 443 : 80);
+ auto port = is_ssl ? 443 : 80;
+ if (!port_str.empty() && !detail::parse_port(port_str, port)) { return; }
if (is_ssl) {
#ifdef CPPHTTPLIB_SSL_ENABLED
if (host_.empty()) { host_ = m[3].str(); }
auto port_str = m[4].str();
- port_ = !port_str.empty() ? std::stoi(port_str) : (is_ssl ? 443 : 80);
+ port_ = is_ssl ? 443 : 80;
+ if (!port_str.empty() && !detail::parse_port(port_str, port_)) { return; }
path_ = m[5].str();
#ifndef CPPHTTPLIB_HTTPLIB_H
#define CPPHTTPLIB_HTTPLIB_H
-#define CPPHTTPLIB_VERSION "0.37.1"
-#define CPPHTTPLIB_VERSION_NUM "0x002501"
+#define CPPHTTPLIB_VERSION "0.37.2"
+#define CPPHTTPLIB_VERSION_NUM "0x002502"
#ifdef _WIN32
#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0A00
return {first + (endptr - s.c_str()), std::errc{}};
}
+inline bool parse_port(const char *s, size_t len, int &port) {
+ int val = 0;
+ auto r = from_chars(s, s + len, val);
+ if (r.ec != std::errc{} || val < 1 || val > 65535) { return false; }
+ port = val;
+ return true;
+}
+
+inline bool parse_port(const std::string &s, int &port) {
+ return parse_port(s.data(), s.size(), port);
+}
+
} // namespace detail
enum SSLVerifierResponse {