|
|
@@ -1357,6 +1357,26 @@ inline bool is_connection_error() {
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
+inline socket_t create_client_socket(
|
|
|
+ const char *host, int port, time_t timeout_sec) {
|
|
|
+ return create_socket(
|
|
|
+ host, port, [=](socket_t sock, struct addrinfo &ai) -> bool {
|
|
|
+ set_nonblocking(sock, true);
|
|
|
+
|
|
|
+ auto ret = ::connect(sock, ai.ai_addr, static_cast<int>(ai.ai_addrlen));
|
|
|
+ if (ret < 0) {
|
|
|
+ if (is_connection_error() ||
|
|
|
+ !wait_until_socket_is_ready(sock, timeout_sec, 0)) {
|
|
|
+ close_socket(sock);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ set_nonblocking(sock, false);
|
|
|
+ return true;
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
inline std::string get_remote_addr(socket_t sock) {
|
|
|
struct sockaddr_storage addr;
|
|
|
socklen_t len = sizeof(addr);
|
|
|
@@ -1542,7 +1562,11 @@ inline uint64_t get_header_value_uint64(const Headers &headers, const char *key,
|
|
|
}
|
|
|
|
|
|
inline bool read_headers(Stream &strm, Headers &headers) {
|
|
|
- static std::regex re(R"((.+?):\s*(.+?)\s*\r\n)");
|
|
|
+ // Horizontal tab and ' ' are considered whitespace and are ignored when on
|
|
|
+ // the left or right side of the header value:
|
|
|
+ // - https://stackoverflow.com/questions/50179659/
|
|
|
+ // - https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html
|
|
|
+ static std::regex re(R"((.+?):[\t ]*(.+?)[\t ]*\r\n)");
|
|
|
|
|
|
const auto bufsiz = 2048;
|
|
|
char buf[bufsiz];
|
|
|
@@ -3166,22 +3190,7 @@ inline Client::~Client() {}
|
|
|
inline bool Client::is_valid() const { return true; }
|
|
|
|
|
|
inline socket_t Client::create_client_socket() const {
|
|
|
- return detail::create_socket(
|
|
|
- host_.c_str(), port_, [=](socket_t sock, struct addrinfo &ai) -> bool {
|
|
|
- detail::set_nonblocking(sock, true);
|
|
|
-
|
|
|
- auto ret = connect(sock, ai.ai_addr, static_cast<int>(ai.ai_addrlen));
|
|
|
- if (ret < 0) {
|
|
|
- if (detail::is_connection_error() ||
|
|
|
- !detail::wait_until_socket_is_ready(sock, timeout_sec_, 0)) {
|
|
|
- detail::close_socket(sock);
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- detail::set_nonblocking(sock, false);
|
|
|
- return true;
|
|
|
- });
|
|
|
+ return detail::create_client_socket(host_.c_str(), port_, timeout_sec_);
|
|
|
}
|
|
|
|
|
|
inline bool Client::read_response_line(Stream &strm, Response &res) {
|