Fix #382
This commit is contained in:
parent
ab96f49766
commit
e1acb949e7
17
httplib.h
17
httplib.h
@ -1923,9 +1923,7 @@ inline ssize_t write_headers(Stream &strm, const T &info,
|
|||||||
const Headers &headers) {
|
const Headers &headers) {
|
||||||
ssize_t write_len = 0;
|
ssize_t write_len = 0;
|
||||||
for (const auto &x : info.headers) {
|
for (const auto &x : info.headers) {
|
||||||
if (x.first == "EXCEPTION_WHAT") {
|
if (x.first == "EXCEPTION_WHAT") { continue; }
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto len =
|
auto len =
|
||||||
strm.write_format("%s: %s\r\n", x.first.c_str(), x.second.c_str());
|
strm.write_format("%s: %s\r\n", x.first.c_str(), x.second.c_str());
|
||||||
if (len < 0) { return len; }
|
if (len < 0) { return len; }
|
||||||
@ -2042,7 +2040,8 @@ inline std::string encode_url(const std::string &s) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string decode_url(const std::string &s) {
|
inline std::string decode_url(const std::string &s,
|
||||||
|
bool convert_plus_to_space) {
|
||||||
std::string result;
|
std::string result;
|
||||||
|
|
||||||
for (size_t i = 0; i < s.size(); i++) {
|
for (size_t i = 0; i < s.size(); i++) {
|
||||||
@ -2068,7 +2067,7 @@ inline std::string decode_url(const std::string &s) {
|
|||||||
result += s[i];
|
result += s[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (s[i] == '+') {
|
} else if (convert_plus_to_space && s[i] == '+') {
|
||||||
result += ' ';
|
result += ' ';
|
||||||
} else {
|
} else {
|
||||||
result += s[i];
|
result += s[i];
|
||||||
@ -2102,7 +2101,7 @@ inline void parse_query_text(const std::string &s, Params ¶ms) {
|
|||||||
val.assign(b2, e2);
|
val.assign(b2, e2);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
params.emplace(key, decode_url(val));
|
params.emplace(decode_url(key, true), decode_url(val, true));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3024,7 +3023,7 @@ inline bool Server::parse_request_line(const char *s, Request &req) {
|
|||||||
req.version = std::string(m[5]);
|
req.version = std::string(m[5]);
|
||||||
req.method = std::string(m[1]);
|
req.method = std::string(m[1]);
|
||||||
req.target = std::string(m[2]);
|
req.target = std::string(m[2]);
|
||||||
req.path = detail::decode_url(m[3]);
|
req.path = detail::decode_url(m[3], false);
|
||||||
|
|
||||||
// Parse query text
|
// Parse query text
|
||||||
auto len = std::distance(m[4].first, m[4].second);
|
auto len = std::distance(m[4].first, m[4].second);
|
||||||
@ -3391,9 +3390,9 @@ inline bool Server::listen_internal() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if __cplusplus > 201703L
|
#if __cplusplus > 201703L
|
||||||
task_queue->enqueue([=, this]() { process_and_close_socket(sock); });
|
task_queue->enqueue([=, this]() { process_and_close_socket(sock); });
|
||||||
#else
|
#else
|
||||||
task_queue->enqueue([=]() { process_and_close_socket(sock); });
|
task_queue->enqueue([=]() { process_and_close_socket(sock); });
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
44
test/test.cc
44
test/test.cc
@ -78,18 +78,18 @@ TEST(ParseQueryTest, ParseQueryString) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(ParamsToQueryTest, ConvertParamsToQuery) {
|
TEST(ParamsToQueryTest, ConvertParamsToQuery) {
|
||||||
Params dic;
|
Params dic;
|
||||||
|
|
||||||
EXPECT_EQ(detail::params_to_query_str(dic), "");
|
EXPECT_EQ(detail::params_to_query_str(dic), "");
|
||||||
|
|
||||||
dic.emplace("key1", "val1");
|
dic.emplace("key1", "val1");
|
||||||
|
|
||||||
EXPECT_EQ(detail::params_to_query_str(dic), "key1=val1");
|
EXPECT_EQ(detail::params_to_query_str(dic), "key1=val1");
|
||||||
|
|
||||||
dic.emplace("key2", "val2");
|
dic.emplace("key2", "val2");
|
||||||
dic.emplace("key3", "val3");
|
dic.emplace("key3", "val3");
|
||||||
|
|
||||||
EXPECT_EQ(detail::params_to_query_str(dic), "key1=val1&key2=val2&key3=val3");
|
EXPECT_EQ(detail::params_to_query_str(dic), "key1=val1&key2=val2&key3=val3");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(GetHeaderValueTest, DefaultValue) {
|
TEST(GetHeaderValueTest, DefaultValue) {
|
||||||
@ -668,7 +668,8 @@ TEST(Server, BindAndListenSeparately) {
|
|||||||
|
|
||||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||||
TEST(SSLServer, BindAndListenSeparately) {
|
TEST(SSLServer, BindAndListenSeparately) {
|
||||||
SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE, CLIENT_CA_CERT_FILE, CLIENT_CA_CERT_DIR);
|
SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE, CLIENT_CA_CERT_FILE,
|
||||||
|
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");
|
||||||
ASSERT_TRUE(svr.is_valid());
|
ASSERT_TRUE(svr.is_valid());
|
||||||
ASSERT_TRUE(port > 0);
|
ASSERT_TRUE(port > 0);
|
||||||
@ -710,6 +711,12 @@ protected:
|
|||||||
[&](const Request & /*req*/, Response &res) {
|
[&](const Request & /*req*/, Response &res) {
|
||||||
res.set_content("Hello World!", "text/plain");
|
res.set_content("Hello World!", "text/plain");
|
||||||
})
|
})
|
||||||
|
.Get("/a\\+\\+b",
|
||||||
|
[&](const Request &req, Response &res) {
|
||||||
|
ASSERT_TRUE(req.has_param("a +b"));
|
||||||
|
auto val = req.get_param_value("a +b");
|
||||||
|
res.set_content(val, "text/plain");
|
||||||
|
})
|
||||||
.Get("/", [&](const Request & /*req*/,
|
.Get("/", [&](const Request & /*req*/,
|
||||||
Response &res) { res.set_redirect("/hi"); })
|
Response &res) { res.set_redirect("/hi"); })
|
||||||
.Post("/person",
|
.Post("/person",
|
||||||
@ -1459,6 +1466,13 @@ TEST_F(ServerTest, EndWithPercentCharacterInQuery) {
|
|||||||
EXPECT_EQ(404, res->status);
|
EXPECT_EQ(404, res->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ServerTest, PlusSignEncoding) {
|
||||||
|
auto res = cli_.Get("/a+%2Bb?a %2bb=a %2Bb");
|
||||||
|
ASSERT_TRUE(res != nullptr);
|
||||||
|
EXPECT_EQ(200, res->status);
|
||||||
|
EXPECT_EQ("a +b", res->body);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(ServerTest, MultipartFormData) {
|
TEST_F(ServerTest, MultipartFormData) {
|
||||||
MultipartFormDataItems items = {
|
MultipartFormDataItems items = {
|
||||||
{"text1", "text default", "", ""},
|
{"text1", "text default", "", ""},
|
||||||
@ -1727,7 +1741,8 @@ TEST_F(ServerTest, PutContentWithDeflate) {
|
|||||||
httplib::Headers headers;
|
httplib::Headers headers;
|
||||||
headers.emplace("Content-Encoding", "deflate");
|
headers.emplace("Content-Encoding", "deflate");
|
||||||
// PUT in deflate format:
|
// PUT in deflate format:
|
||||||
auto res = cli_.Put("/put", headers, "\170\234\013\010\015\001\0\001\361\0\372", "text/plain");
|
auto res = cli_.Put("/put", headers,
|
||||||
|
"\170\234\013\010\015\001\0\001\361\0\372", "text/plain");
|
||||||
|
|
||||||
ASSERT_TRUE(res != nullptr);
|
ASSERT_TRUE(res != nullptr);
|
||||||
EXPECT_EQ(200, res->status);
|
EXPECT_EQ(200, res->status);
|
||||||
@ -2050,7 +2065,7 @@ TEST(ServerRequestParsingTest, TrimWhitespaceFromHeaderValues) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sends a raw request and verifies that there isn't a crash or exception.
|
// Sends a raw request and verifies that there isn't a crash or exception.
|
||||||
static void test_raw_request(const std::string& req) {
|
static void test_raw_request(const std::string &req) {
|
||||||
Server svr;
|
Server svr;
|
||||||
svr.Get("/hi", [&](const Request & /*req*/, Response &res) {
|
svr.Get("/hi", [&](const Request & /*req*/, Response &res) {
|
||||||
res.set_content("ok", "text/plain");
|
res.set_content("ok", "text/plain");
|
||||||
@ -2208,11 +2223,10 @@ TEST(MountTest, Unmount) {
|
|||||||
TEST(ExceptionTest, ThrowExceptionInHandler) {
|
TEST(ExceptionTest, ThrowExceptionInHandler) {
|
||||||
Server svr;
|
Server svr;
|
||||||
|
|
||||||
svr.Get("/hi",
|
svr.Get("/hi", [&](const Request & /*req*/, Response &res) {
|
||||||
[&](const Request & /*req*/, Response &res) {
|
throw std::runtime_error("exception...");
|
||||||
throw std::runtime_error("exception...");
|
res.set_content("Hello World!", "text/plain");
|
||||||
res.set_content("Hello World!", "text/plain");
|
});
|
||||||
});
|
|
||||||
|
|
||||||
auto listen_thread = std::thread([&svr]() { svr.listen("localhost", PORT); });
|
auto listen_thread = std::thread([&svr]() { svr.listen("localhost", PORT); });
|
||||||
while (!svr.is_running()) {
|
while (!svr.is_running()) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user