mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2025-05-15 09:18:27 +00:00
Fix #738
This commit is contained in:
parent
6613d7b7ad
commit
f086bf5310
2 changed files with 68 additions and 33 deletions
27
httplib.h
27
httplib.h
|
@ -692,7 +692,7 @@ private:
|
||||||
const Request &req, Response &res);
|
const Request &req, Response &res);
|
||||||
bool write_response_core(Stream &strm, bool close_connection,
|
bool write_response_core(Stream &strm, bool close_connection,
|
||||||
const Request &req, Response &res,
|
const Request &req, Response &res,
|
||||||
std::string &content_type, std::string &boundary);
|
bool need_apply_ranges);
|
||||||
bool write_content_with_provider(Stream &strm, const Request &req,
|
bool write_content_with_provider(Stream &strm, const Request &req,
|
||||||
Response &res, const std::string &boundary,
|
Response &res, const std::string &boundary,
|
||||||
const std::string &content_type);
|
const std::string &content_type);
|
||||||
|
@ -3769,7 +3769,8 @@ inline ssize_t SocketStream::read(char *ptr, size_t size) {
|
||||||
}
|
}
|
||||||
return recv(sock_, ptr, static_cast<int>(size), CPPHTTPLIB_RECV_FLAGS);
|
return recv(sock_, ptr, static_cast<int>(size), CPPHTTPLIB_RECV_FLAGS);
|
||||||
#else
|
#else
|
||||||
return handle_EINTR([&]() { return recv(sock_, ptr, size, CPPHTTPLIB_RECV_FLAGS); });
|
return handle_EINTR(
|
||||||
|
[&]() { return recv(sock_, ptr, size, CPPHTTPLIB_RECV_FLAGS); });
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3782,7 +3783,8 @@ inline ssize_t SocketStream::write(const char *ptr, size_t size) {
|
||||||
}
|
}
|
||||||
return send(sock_, ptr, static_cast<int>(size), CPPHTTPLIB_SEND_FLAGS);
|
return send(sock_, ptr, static_cast<int>(size), CPPHTTPLIB_SEND_FLAGS);
|
||||||
#else
|
#else
|
||||||
return handle_EINTR([&]() { return send(sock_, ptr, size, CPPHTTPLIB_SEND_FLAGS); });
|
return handle_EINTR(
|
||||||
|
[&]() { return send(sock_, ptr, size, CPPHTTPLIB_SEND_FLAGS); });
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4022,32 +4024,27 @@ inline bool Server::parse_request_line(const char *s, Request &req) {
|
||||||
|
|
||||||
inline bool Server::write_response(Stream &strm, bool close_connection,
|
inline bool Server::write_response(Stream &strm, bool close_connection,
|
||||||
const Request &req, Response &res) {
|
const Request &req, Response &res) {
|
||||||
std::string content_type;
|
return write_response_core(strm, close_connection, req, res, false);
|
||||||
std::string boundary;
|
|
||||||
return write_response_core(strm, close_connection, req, res, content_type,
|
|
||||||
boundary);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool Server::write_response_with_content(Stream &strm,
|
inline bool Server::write_response_with_content(Stream &strm,
|
||||||
bool close_connection,
|
bool close_connection,
|
||||||
const Request &req,
|
const Request &req,
|
||||||
Response &res) {
|
Response &res) {
|
||||||
std::string content_type;
|
return write_response_core(strm, close_connection, req, res, true);
|
||||||
std::string boundary;
|
|
||||||
apply_ranges(req, res, content_type, boundary);
|
|
||||||
|
|
||||||
return write_response_core(strm, close_connection, req, res, content_type,
|
|
||||||
boundary);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool Server::write_response_core(Stream &strm, bool close_connection,
|
inline bool Server::write_response_core(Stream &strm, bool close_connection,
|
||||||
const Request &req, Response &res,
|
const Request &req, Response &res,
|
||||||
std::string &content_type,
|
bool need_apply_ranges) {
|
||||||
std::string &boundary) {
|
|
||||||
assert(res.status != -1);
|
assert(res.status != -1);
|
||||||
|
|
||||||
if (400 <= res.status && error_handler_) { error_handler_(req, res); }
|
if (400 <= res.status && error_handler_) { error_handler_(req, res); }
|
||||||
|
|
||||||
|
std::string content_type;
|
||||||
|
std::string boundary;
|
||||||
|
if (need_apply_ranges) { apply_ranges(req, res, content_type, boundary); }
|
||||||
|
|
||||||
// Headers
|
// Headers
|
||||||
if (close_connection || req.get_header_value("Connection") == "close") {
|
if (close_connection || req.get_header_value("Connection") == "close") {
|
||||||
res.set_header("Connection", "close");
|
res.set_header("Connection", "close");
|
||||||
|
|
54
test/test.cc
54
test/test.cc
|
@ -841,7 +841,7 @@ TEST(UrlWithSpace, Redirect) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TEST(Server, BindDualStack) {
|
TEST(BindServerTest, BindDualStack) {
|
||||||
Server svr;
|
Server svr;
|
||||||
|
|
||||||
svr.Get("/1", [&](const Request & /*req*/, Response &res) {
|
svr.Get("/1", [&](const Request & /*req*/, Response &res) {
|
||||||
|
@ -874,7 +874,7 @@ TEST(Server, BindDualStack) {
|
||||||
ASSERT_FALSE(svr.is_running());
|
ASSERT_FALSE(svr.is_running());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Server, BindAndListenSeparately) {
|
TEST(BindServerTest, BindAndListenSeparately) {
|
||||||
Server svr;
|
Server svr;
|
||||||
int port = svr.bind_to_any_port("0.0.0.0");
|
int port = svr.bind_to_any_port("0.0.0.0");
|
||||||
ASSERT_TRUE(svr.is_valid());
|
ASSERT_TRUE(svr.is_valid());
|
||||||
|
@ -883,7 +883,7 @@ TEST(Server, BindAndListenSeparately) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||||
TEST(SSLServer, BindAndListenSeparately) {
|
TEST(BindServerTest, BindAndListenSeparatelySSL) {
|
||||||
SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE, CLIENT_CA_CERT_FILE,
|
SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE, CLIENT_CA_CERT_FILE,
|
||||||
CLIENT_CA_CERT_DIR);
|
CLIENT_CA_CERT_DIR);
|
||||||
int port = svr.bind_to_any_port("0.0.0.0");
|
int port = svr.bind_to_any_port("0.0.0.0");
|
||||||
|
@ -893,6 +893,41 @@ TEST(SSLServer, BindAndListenSeparately) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
TEST(ErrorHandlerTest, ContentLength) {
|
||||||
|
Server svr;
|
||||||
|
|
||||||
|
svr.set_error_handler([](const Request & /*req*/, Response &res) {
|
||||||
|
res.status = 200;
|
||||||
|
res.set_content("abcdefghijklmnopqrstuvwxyz",
|
||||||
|
"text/html"); // <= Content-Length still 13
|
||||||
|
});
|
||||||
|
|
||||||
|
svr.Get("/hi", [](const Request & /*req*/, Response &res) {
|
||||||
|
res.set_content("Hello World!\n", "text/plain");
|
||||||
|
res.status = 524;
|
||||||
|
});
|
||||||
|
|
||||||
|
auto thread = std::thread([&]() { svr.listen(HOST, PORT); });
|
||||||
|
|
||||||
|
// Give GET time to get a few messages.
|
||||||
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||||
|
|
||||||
|
{
|
||||||
|
Client cli(HOST, PORT);
|
||||||
|
|
||||||
|
auto res = cli.Get("/hi");
|
||||||
|
ASSERT_TRUE(res);
|
||||||
|
EXPECT_EQ(200, res->status);
|
||||||
|
EXPECT_EQ("text/html", res->get_header_value("Content-Type"));
|
||||||
|
EXPECT_EQ("26", res->get_header_value("Content-Length"));
|
||||||
|
EXPECT_EQ("abcdefghijklmnopqrstuvwxyz", res->body);
|
||||||
|
}
|
||||||
|
|
||||||
|
svr.stop();
|
||||||
|
thread.join();
|
||||||
|
ASSERT_FALSE(svr.is_running());
|
||||||
|
}
|
||||||
|
|
||||||
class ServerTest : public ::testing::Test {
|
class ServerTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
ServerTest()
|
ServerTest()
|
||||||
|
@ -3474,13 +3509,15 @@ TEST(SSLClientServerTest, TrustDirOptional) {
|
||||||
TEST(SSLClientServerTest, SSLConnectTimeout) {
|
TEST(SSLClientServerTest, SSLConnectTimeout) {
|
||||||
class NoListenSSLServer : public SSLServer {
|
class NoListenSSLServer : public SSLServer {
|
||||||
public:
|
public:
|
||||||
NoListenSSLServer(const char *cert_path, const char *private_key_path, const char *client_ca_cert_file_path,
|
NoListenSSLServer(const char *cert_path, const char *private_key_path,
|
||||||
|
const char *client_ca_cert_file_path,
|
||||||
const char *client_ca_cert_dir_path = nullptr)
|
const char *client_ca_cert_dir_path = nullptr)
|
||||||
: SSLServer(cert_path, private_key_path, client_ca_cert_file_path, client_ca_cert_dir_path)
|
: SSLServer(cert_path, private_key_path, client_ca_cert_file_path,
|
||||||
, stop_(false)
|
client_ca_cert_dir_path),
|
||||||
{}
|
stop_(false) {}
|
||||||
|
|
||||||
bool stop_;
|
bool stop_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool process_and_close_socket(socket_t /*sock*/) override {
|
bool process_and_close_socket(socket_t /*sock*/) override {
|
||||||
// Don't create SSL context
|
// Don't create SSL context
|
||||||
|
@ -3490,7 +3527,8 @@ TEST(SSLClientServerTest, SSLConnectTimeout) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
NoListenSSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE, CLIENT_CA_CERT_FILE);
|
NoListenSSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE,
|
||||||
|
CLIENT_CA_CERT_FILE);
|
||||||
ASSERT_TRUE(svr.is_valid());
|
ASSERT_TRUE(svr.is_valid());
|
||||||
|
|
||||||
svr.Get("/test", [&](const Request &, Response &res) {
|
svr.Get("/test", [&](const Request &, Response &res) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue