mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2025-05-12 14:11:39 +00:00
fix #116
This commit is contained in:
parent
d0090b158f
commit
b5927aec12
45
httplib.h
45
httplib.h
@ -132,11 +132,13 @@ struct Request {
|
|||||||
Progress progress;
|
Progress progress;
|
||||||
|
|
||||||
bool has_header(const char* key) const;
|
bool has_header(const char* key) const;
|
||||||
std::string get_header_value(const char* key) const;
|
std::string get_header_value(const char* key, size_t id = 0) const;
|
||||||
|
size_t get_header_value_count(const char* key) const;
|
||||||
void set_header(const char* key, const char* val);
|
void set_header(const char* key, const char* val);
|
||||||
|
|
||||||
bool has_param(const char* key) const;
|
bool has_param(const char* key) const;
|
||||||
std::string get_param_value(const char* key) const;
|
std::string get_param_value(const char* key, size_t id = 0) const;
|
||||||
|
size_t get_param_value_count(const char* key) const;
|
||||||
|
|
||||||
bool has_file(const char* key) const;
|
bool has_file(const char* key) const;
|
||||||
MultipartFile get_file_value(const char* key) const;
|
MultipartFile get_file_value(const char* key) const;
|
||||||
@ -150,7 +152,8 @@ struct Response {
|
|||||||
std::function<std::string (uint64_t offset)> streamcb;
|
std::function<std::string (uint64_t offset)> streamcb;
|
||||||
|
|
||||||
bool has_header(const char* key) const;
|
bool has_header(const char* key) const;
|
||||||
std::string get_header_value(const char* key) const;
|
std::string get_header_value(const char* key, size_t id = 0) const;
|
||||||
|
size_t get_header_value_count(const char* key) const;
|
||||||
void set_header(const char* key, const char* val);
|
void set_header(const char* key, const char* val);
|
||||||
|
|
||||||
void set_redirect(const char* uri);
|
void set_redirect(const char* uri);
|
||||||
@ -771,9 +774,10 @@ inline bool has_header(const Headers& headers, const char* key)
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline const char* get_header_value(
|
inline const char* get_header_value(
|
||||||
const Headers& headers, const char* key, const char* def = nullptr)
|
const Headers& headers, const char* key, size_t id = 0, const char* def = nullptr)
|
||||||
{
|
{
|
||||||
auto it = headers.find(key);
|
auto it = headers.find(key);
|
||||||
|
std::advance(it, id);
|
||||||
if (it != headers.end()) {
|
if (it != headers.end()) {
|
||||||
return it->second.c_str();
|
return it->second.c_str();
|
||||||
}
|
}
|
||||||
@ -905,14 +909,14 @@ bool read_content(Stream& strm, T& x, Progress progress = Progress())
|
|||||||
if (has_header(x.headers, "Content-Length")) {
|
if (has_header(x.headers, "Content-Length")) {
|
||||||
auto len = get_header_value_int(x.headers, "Content-Length", 0);
|
auto len = get_header_value_int(x.headers, "Content-Length", 0);
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
const auto& encoding = get_header_value(x.headers, "Transfer-Encoding", "");
|
const auto& encoding = get_header_value(x.headers, "Transfer-Encoding", 0, "");
|
||||||
if (!strcasecmp(encoding, "chunked")) {
|
if (!strcasecmp(encoding, "chunked")) {
|
||||||
return read_content_chunked(strm, x.body);
|
return read_content_chunked(strm, x.body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return read_content_with_length(strm, x.body, len, progress);
|
return read_content_with_length(strm, x.body, len, progress);
|
||||||
} else {
|
} else {
|
||||||
const auto& encoding = get_header_value(x.headers, "Transfer-Encoding", "");
|
const auto& encoding = get_header_value(x.headers, "Transfer-Encoding", 0, "");
|
||||||
if (!strcasecmp(encoding, "chunked")) {
|
if (!strcasecmp(encoding, "chunked")) {
|
||||||
return read_content_chunked(strm, x.body);
|
return read_content_chunked(strm, x.body);
|
||||||
}
|
}
|
||||||
@ -1333,9 +1337,15 @@ inline bool Request::has_header(const char* key) const
|
|||||||
return detail::has_header(headers, key);
|
return detail::has_header(headers, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string Request::get_header_value(const char* key) const
|
inline std::string Request::get_header_value(const char* key, size_t id) const
|
||||||
{
|
{
|
||||||
return detail::get_header_value(headers, key, "");
|
return detail::get_header_value(headers, key, id, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t Request::get_header_value_count(const char* key) const
|
||||||
|
{
|
||||||
|
auto r = headers.equal_range(key);
|
||||||
|
return std::distance(r.first, r.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Request::set_header(const char* key, const char* val)
|
inline void Request::set_header(const char* key, const char* val)
|
||||||
@ -1348,15 +1358,22 @@ inline bool Request::has_param(const char* key) const
|
|||||||
return params.find(key) != params.end();
|
return params.find(key) != params.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string Request::get_param_value(const char* key) const
|
inline std::string Request::get_param_value(const char* key, size_t id) const
|
||||||
{
|
{
|
||||||
auto it = params.find(key);
|
auto it = params.find(key);
|
||||||
|
std::advance(it, id);
|
||||||
if (it != params.end()) {
|
if (it != params.end()) {
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline size_t Request::get_param_value_count(const char* key) const
|
||||||
|
{
|
||||||
|
auto r = params.equal_range(key);
|
||||||
|
return std::distance(r.first, r.second);
|
||||||
|
}
|
||||||
|
|
||||||
inline bool Request::has_file(const char* key) const
|
inline bool Request::has_file(const char* key) const
|
||||||
{
|
{
|
||||||
return files.find(key) != files.end();
|
return files.find(key) != files.end();
|
||||||
@ -1377,9 +1394,15 @@ inline bool Response::has_header(const char* key) const
|
|||||||
return headers.find(key) != headers.end();
|
return headers.find(key) != headers.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string Response::get_header_value(const char* key) const
|
inline std::string Response::get_header_value(const char* key, size_t id) const
|
||||||
{
|
{
|
||||||
return detail::get_header_value(headers, key, "");
|
return detail::get_header_value(headers, key, id, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t Response::get_header_value_count(const char* key) const
|
||||||
|
{
|
||||||
|
auto r = headers.equal_range(key);
|
||||||
|
return std::distance(r.first, r.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Response::set_header(const char* key, const char* val)
|
inline void Response::set_header(const char* key, const char* val)
|
||||||
|
27
test/test.cc
27
test/test.cc
@ -71,7 +71,7 @@ TEST(ParseQueryTest, ParseQueryString)
|
|||||||
TEST(GetHeaderValueTest, DefaultValue)
|
TEST(GetHeaderValueTest, DefaultValue)
|
||||||
{
|
{
|
||||||
Headers headers = {{"Dummy","Dummy"}};
|
Headers headers = {{"Dummy","Dummy"}};
|
||||||
auto val = detail::get_header_value(headers, "Content-Type", "text/plain");
|
auto val = detail::get_header_value(headers, "Content-Type", 0, "text/plain");
|
||||||
EXPECT_STREQ("text/plain", val);
|
EXPECT_STREQ("text/plain", val);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ TEST(GetHeaderValueTest, DefaultValueInt)
|
|||||||
TEST(GetHeaderValueTest, RegularValue)
|
TEST(GetHeaderValueTest, RegularValue)
|
||||||
{
|
{
|
||||||
Headers headers = {{"Content-Type", "text/html"}, {"Dummy", "Dummy"}};
|
Headers headers = {{"Content-Type", "text/html"}, {"Dummy", "Dummy"}};
|
||||||
auto val = detail::get_header_value(headers, "Content-Type", "text/plain");
|
auto val = detail::get_header_value(headers, "Content-Type", 0, "text/plain");
|
||||||
EXPECT_STREQ("text/html", val);
|
EXPECT_STREQ("text/html", val);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,25 +100,25 @@ TEST(GetHeaderValueTest, Range)
|
|||||||
{
|
{
|
||||||
{
|
{
|
||||||
Headers headers = { make_range_header(1) };
|
Headers headers = { make_range_header(1) };
|
||||||
auto val = detail::get_header_value(headers, "Range", 0);
|
auto val = detail::get_header_value(headers, "Range", 0, 0);
|
||||||
EXPECT_STREQ("bytes=1-", val);
|
EXPECT_STREQ("bytes=1-", val);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Headers headers = { make_range_header(1, 10) };
|
Headers headers = { make_range_header(1, 10) };
|
||||||
auto val = detail::get_header_value(headers, "Range", 0);
|
auto val = detail::get_header_value(headers, "Range", 0, 0);
|
||||||
EXPECT_STREQ("bytes=1-10", val);
|
EXPECT_STREQ("bytes=1-10", val);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Headers headers = { make_range_header(1, 10, 100) };
|
Headers headers = { make_range_header(1, 10, 100) };
|
||||||
auto val = detail::get_header_value(headers, "Range", 0);
|
auto val = detail::get_header_value(headers, "Range", 0, 0);
|
||||||
EXPECT_STREQ("bytes=1-10, 100-", val);
|
EXPECT_STREQ("bytes=1-10, 100-", val);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Headers headers = { make_range_header(1, 10, 100, 200) };
|
Headers headers = { make_range_header(1, 10, 100, 200) };
|
||||||
auto val = detail::get_header_value(headers, "Range", 0);
|
auto val = detail::get_header_value(headers, "Range", 0, 0);
|
||||||
EXPECT_STREQ("bytes=1-10, 100-200", val);
|
EXPECT_STREQ("bytes=1-10, 100-200", val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -432,7 +432,12 @@ protected:
|
|||||||
EXPECT_EQ(LONG_QUERY_URL, req.target);
|
EXPECT_EQ(LONG_QUERY_URL, req.target);
|
||||||
EXPECT_EQ(LONG_QUERY_VALUE, req.get_param_value("key"));
|
EXPECT_EQ(LONG_QUERY_VALUE, req.get_param_value("key"));
|
||||||
})
|
})
|
||||||
|
.Get("/array-param", [&](const Request& req, Response& /*res*/) {
|
||||||
|
EXPECT_EQ(3u, req.get_param_value_count("array"));
|
||||||
|
EXPECT_EQ("value1", req.get_param_value("array", 0));
|
||||||
|
EXPECT_EQ("value2", req.get_param_value("array", 1));
|
||||||
|
EXPECT_EQ("value3", req.get_param_value("array", 2));
|
||||||
|
})
|
||||||
#ifdef CPPHTTPLIB_ZLIB_SUPPORT
|
#ifdef CPPHTTPLIB_ZLIB_SUPPORT
|
||||||
.Get("/gzip", [&](const Request& /*req*/, Response& res) {
|
.Get("/gzip", [&](const Request& /*req*/, Response& res) {
|
||||||
res.set_content("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", "text/plain");
|
res.set_content("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", "text/plain");
|
||||||
@ -497,6 +502,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(1, res->get_header_value_count("Content-Type"));
|
||||||
EXPECT_EQ("close", res->get_header_value("Connection"));
|
EXPECT_EQ("close", res->get_header_value("Connection"));
|
||||||
EXPECT_EQ("Hello World!", res->body);
|
EXPECT_EQ("Hello World!", res->body);
|
||||||
}
|
}
|
||||||
@ -936,6 +942,13 @@ TEST_F(ServerTest, URL)
|
|||||||
EXPECT_EQ(200, res->status);
|
EXPECT_EQ(200, res->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ServerTest, ArrayParam)
|
||||||
|
{
|
||||||
|
auto res = cli_.Get("/array-param?array=value1&array=value2&array=value3");
|
||||||
|
ASSERT_TRUE(res != nullptr);
|
||||||
|
EXPECT_EQ(200, res->status);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CPPHTTPLIB_ZLIB_SUPPORT
|
#ifdef CPPHTTPLIB_ZLIB_SUPPORT
|
||||||
TEST_F(ServerTest, Gzip)
|
TEST_F(ServerTest, Gzip)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user