mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2025-05-15 17:28:29 +00:00
Fixed problem with connection close
This commit is contained in:
parent
312a8d7523
commit
7b9d752583
2 changed files with 46 additions and 30 deletions
73
httplib.h
73
httplib.h
|
@ -216,7 +216,7 @@ public:
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool process_request(Stream& strm, bool last_connection);
|
bool process_request(Stream& strm, bool last_connection, bool& connection_close);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::vector<std::pair<std::regex, Handler>> Handlers;
|
typedef std::vector<std::pair<std::regex, Handler>> Handlers;
|
||||||
|
@ -285,7 +285,7 @@ public:
|
||||||
bool send(Request& req, Response& res);
|
bool send(Request& req, Response& res);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool process_request(Stream& strm, Request& req, Response& res);
|
bool process_request(Stream& strm, Request& req, Response& res, bool& connection_close);
|
||||||
|
|
||||||
const std::string host_;
|
const std::string host_;
|
||||||
const int port_;
|
const int port_;
|
||||||
|
@ -503,17 +503,21 @@ inline bool read_and_close_socket(socket_t sock, bool keep_alive, T callback)
|
||||||
detail::select_read(sock,
|
detail::select_read(sock,
|
||||||
CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND,
|
CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND,
|
||||||
CPPHTTPLIB_KEEPALIVE_TIMEOUT_USECOND) > 0) {
|
CPPHTTPLIB_KEEPALIVE_TIMEOUT_USECOND) > 0) {
|
||||||
auto last_connection = count == 1;
|
|
||||||
SocketStream strm(sock);
|
SocketStream strm(sock);
|
||||||
ret = callback(strm, last_connection);
|
auto last_connection = count == 1;
|
||||||
if (!ret) {
|
auto connection_close = false;
|
||||||
|
|
||||||
|
ret = callback(strm, last_connection, connection_close);
|
||||||
|
if (!ret || connection_close) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
count--;
|
count--;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
SocketStream strm(sock);
|
SocketStream strm(sock);
|
||||||
ret = callback(strm, true);
|
auto dummy_connection_close = false;
|
||||||
|
ret = callback(strm, true, dummy_connection_close);
|
||||||
}
|
}
|
||||||
|
|
||||||
close_socket(sock);
|
close_socket(sock);
|
||||||
|
@ -1535,7 +1539,9 @@ inline void Server::write_response(Stream& strm, bool last_connection, const Req
|
||||||
detail::status_message(res.status));
|
detail::status_message(res.status));
|
||||||
|
|
||||||
// Headers
|
// Headers
|
||||||
if (!res.has_header("Connection") && (last_connection || req.version == "HTTP/1.0")) {
|
if (last_connection ||
|
||||||
|
req.version == "HTTP/1.0" ||
|
||||||
|
req.get_header_value("Connection") == "close") {
|
||||||
res.set_header("Connection", "close");
|
res.set_header("Connection", "close");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1724,7 +1730,7 @@ inline bool Server::dispatch_request(Request& req, Response& res, Handlers& hand
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool Server::process_request(Stream& strm, bool last_connection)
|
inline bool Server::process_request(Stream& strm, bool last_connection, bool& connection_close)
|
||||||
{
|
{
|
||||||
const auto bufsiz = 2048;
|
const auto bufsiz = 2048;
|
||||||
char buf[bufsiz];
|
char buf[bufsiz];
|
||||||
|
@ -1750,7 +1756,8 @@ inline bool Server::process_request(Stream& strm, bool last_connection)
|
||||||
|
|
||||||
auto ret = true;
|
auto ret = true;
|
||||||
if (req.get_header_value("Connection") == "close") {
|
if (req.get_header_value("Connection") == "close") {
|
||||||
ret = false;
|
// ret = false;
|
||||||
|
connection_close = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
req.set_header("REMOTE_ADDR", strm.get_remote_addr().c_str());
|
req.set_header("REMOTE_ADDR", strm.get_remote_addr().c_str());
|
||||||
|
@ -1810,8 +1817,8 @@ inline bool Server::read_and_close_socket(socket_t sock)
|
||||||
return detail::read_and_close_socket(
|
return detail::read_and_close_socket(
|
||||||
sock,
|
sock,
|
||||||
true,
|
true,
|
||||||
[this](Stream& strm, bool last_connection) {
|
[this](Stream& strm, bool last_connection, bool& connection_close) {
|
||||||
return process_request(strm, last_connection);
|
return process_request(strm, last_connection, connection_close);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1910,11 +1917,10 @@ inline void Client::write_request(Stream& strm, Request& req)
|
||||||
req.set_header("User-Agent", "cpp-httplib/0.2");
|
req.set_header("User-Agent", "cpp-httplib/0.2");
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: if (!req.has_header("Connection") &&
|
// TODO: Support KeepAlive connection
|
||||||
// (last_connection || http_version_ == detail::HttpVersion::v1_0)) {
|
// if (!req.has_header("Connection")) {
|
||||||
if (!req.has_header("Connection")) {
|
|
||||||
req.set_header("Connection", "close");
|
req.set_header("Connection", "close");
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (!req.body.empty()) {
|
if (!req.body.empty()) {
|
||||||
if (!req.has_header("Content-Type")) {
|
if (!req.has_header("Content-Type")) {
|
||||||
|
@ -1938,7 +1944,7 @@ inline void Client::write_request(Stream& strm, Request& req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool Client::process_request(Stream& strm, Request& req, Response& res)
|
inline bool Client::process_request(Stream& strm, Request& req, Response& res, bool& connection_close)
|
||||||
{
|
{
|
||||||
// Send request
|
// Send request
|
||||||
write_request(strm, req);
|
write_request(strm, req);
|
||||||
|
@ -1948,8 +1954,9 @@ inline bool Client::process_request(Stream& strm, Request& req, Response& res)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Check if 'Connection' header is 'close' or HTTP version is 1.0,
|
if (res.get_header_value("Connection") == "close" || res.version == "HTTP/1.0") {
|
||||||
// then close socket...
|
connection_close = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Body
|
// Body
|
||||||
if (req.method != "HEAD") {
|
if (req.method != "HEAD") {
|
||||||
|
@ -1971,8 +1978,11 @@ inline bool Client::process_request(Stream& strm, Request& req, Response& res)
|
||||||
|
|
||||||
inline bool Client::read_and_close_socket(socket_t sock, Request& req, Response& res)
|
inline bool Client::read_and_close_socket(socket_t sock, Request& req, Response& res)
|
||||||
{
|
{
|
||||||
return detail::read_and_close_socket(sock, false, [&](Stream& strm, bool /*last_connection*/) {
|
return detail::read_and_close_socket(
|
||||||
return process_request(strm, req, res);
|
sock,
|
||||||
|
false,
|
||||||
|
[&](Stream& strm, bool /*last_connection*/, bool& connection_close) {
|
||||||
|
return process_request(strm, req, res, connection_close);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2118,7 +2128,8 @@ namespace detail {
|
||||||
template <typename U, typename V, typename T>
|
template <typename U, typename V, typename T>
|
||||||
inline bool read_and_close_socket_ssl(
|
inline bool read_and_close_socket_ssl(
|
||||||
socket_t sock, bool keep_alive,
|
socket_t sock, bool keep_alive,
|
||||||
// TODO: OpenSSL 1.0.2 occasionally crashes... The upcoming 1.1.0 is going to be thread safe.
|
// TODO: OpenSSL 1.0.2 occasionally crashes...
|
||||||
|
// The upcoming 1.1.0 is going to be thread safe.
|
||||||
SSL_CTX* ctx, std::mutex& ctx_mutex,
|
SSL_CTX* ctx, std::mutex& ctx_mutex,
|
||||||
U SSL_connect_or_accept, V setup,
|
U SSL_connect_or_accept, V setup,
|
||||||
T callback)
|
T callback)
|
||||||
|
@ -2148,17 +2159,21 @@ inline bool read_and_close_socket_ssl(
|
||||||
detail::select_read(sock,
|
detail::select_read(sock,
|
||||||
CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND,
|
CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND,
|
||||||
CPPHTTPLIB_KEEPALIVE_TIMEOUT_USECOND) > 0) {
|
CPPHTTPLIB_KEEPALIVE_TIMEOUT_USECOND) > 0) {
|
||||||
auto last_connection = count == 1;
|
|
||||||
SSLSocketStream strm(sock, ssl);
|
SSLSocketStream strm(sock, ssl);
|
||||||
ret = callback(strm, last_connection);
|
auto last_connection = count == 1;
|
||||||
if (!ret) {
|
auto connection_close = false;
|
||||||
|
|
||||||
|
ret = callback(strm, last_connection, connection_close);
|
||||||
|
if (!ret || connection_close) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
count--;
|
count--;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
SSLSocketStream strm(sock, ssl);
|
SSLSocketStream strm(sock, ssl);
|
||||||
ret = callback(strm, true);
|
auto dummy_connection_close = false;
|
||||||
|
ret = callback(strm, true, dummy_connection_close);
|
||||||
}
|
}
|
||||||
|
|
||||||
SSL_shutdown(ssl);
|
SSL_shutdown(ssl);
|
||||||
|
@ -2257,8 +2272,8 @@ inline bool SSLServer::read_and_close_socket(socket_t sock)
|
||||||
ctx_, ctx_mutex_,
|
ctx_, ctx_mutex_,
|
||||||
SSL_accept,
|
SSL_accept,
|
||||||
[](SSL* /*ssl*/) {},
|
[](SSL* /*ssl*/) {},
|
||||||
[this](Stream& strm, bool last_connection) {
|
[this](Stream& strm, bool last_connection, bool& connection_close) {
|
||||||
return process_request(strm, last_connection);
|
return process_request(strm, last_connection, connection_close);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2290,8 +2305,8 @@ inline bool SSLClient::read_and_close_socket(socket_t sock, Request& req, Respon
|
||||||
[&](SSL* ssl) {
|
[&](SSL* ssl) {
|
||||||
SSL_set_tlsext_host_name(ssl, host_.c_str());
|
SSL_set_tlsext_host_name(ssl, host_.c_str());
|
||||||
},
|
},
|
||||||
[&](Stream& strm, bool /*last_connection*/) {
|
[&](Stream& strm, bool /*last_connection*/, bool& connection_close) {
|
||||||
return process_request(strm, req, res);
|
return process_request(strm, req, res, connection_close);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -393,6 +393,7 @@ TEST_F(ServerTest, GetMethod200)
|
||||||
EXPECT_EQ("HTTP/1.1", res->version);
|
EXPECT_EQ("HTTP/1.1", res->version);
|
||||||
EXPECT_EQ(200, res->status);
|
EXPECT_EQ(200, res->status);
|
||||||
EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
|
EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
|
||||||
|
EXPECT_EQ("close", res->get_header_value("Connection"));
|
||||||
EXPECT_EQ("Hello World!", res->body);
|
EXPECT_EQ("Hello World!", res->body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue