mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2025-05-11 21:53:57 +00:00
Fixed #33
This commit is contained in:
parent
c76d0e4ab3
commit
7e5db48bdf
19
README.md
19
README.md
@ -126,15 +126,28 @@ auto res = cli.post("/post", params);
|
|||||||
httplib::Client client(url, port);
|
httplib::Client client(url, port);
|
||||||
|
|
||||||
// prints: 0 / 000 bytes => 50% complete
|
// prints: 0 / 000 bytes => 50% complete
|
||||||
std::shared_ptr<httplib::Response> res =
|
std::shared_ptr<httplib::Response> res =
|
||||||
cli.get("/", [](int64_t len, int64_t total) {
|
cli.get("/", [](uint64_t len, uint64_t total) {
|
||||||
printf("%lld / %lld bytes => %d%% complete\n",
|
printf("%lld / %lld bytes => %d%% complete\n",
|
||||||
len, total,
|
len, total,
|
||||||
(int)((len/total)*100));
|
(int)((len/total)*100));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Range (HTTP/1.1)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
httplib::Client cli("httpbin.org", 80, httplib::HttpVersion::v1_1);
|
||||||
|
|
||||||
|
// 'Range: bytes=1-10'
|
||||||
|
httplib::Headers headers = { httplib::make_range_header(1, 10) };
|
||||||
|
|
||||||
|
auto res = cli.get("/range/32", headers);
|
||||||
|
// res->status should be 206.
|
||||||
|
// res->body should be "bcdefghijk".
|
||||||
|
```
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
This feature was contributed by [underscorediscovery](https://github.com/yhirose/cpp-httplib/pull/23).
|
This feature was contributed by [underscorediscovery](https://github.com/yhirose/cpp-httplib/pull/23).
|
||||||
|
114
httplib.h
114
httplib.h
@ -91,9 +91,13 @@ struct ci {
|
|||||||
enum class HttpVersion { v1_0 = 0, v1_1 };
|
enum class HttpVersion { v1_0 = 0, v1_1 };
|
||||||
|
|
||||||
typedef std::multimap<std::string, std::string, detail::ci> Headers;
|
typedef std::multimap<std::string, std::string, detail::ci> Headers;
|
||||||
|
|
||||||
|
template<typename uint64_t, typename... Args>
|
||||||
|
std::pair<std::string, std::string> make_range_header(uint64_t value, Args... args);
|
||||||
|
|
||||||
typedef std::multimap<std::string, std::string> Params;
|
typedef std::multimap<std::string, std::string> Params;
|
||||||
typedef std::smatch Match;
|
typedef std::smatch Match;
|
||||||
typedef std::function<void (int64_t current, int64_t total)> Progress;
|
typedef std::function<void (uint64_t current, uint64_t total)> Progress;
|
||||||
|
|
||||||
struct MultipartFile {
|
struct MultipartFile {
|
||||||
std::string filename;
|
std::string filename;
|
||||||
@ -111,11 +115,11 @@ struct Request {
|
|||||||
Params params;
|
Params params;
|
||||||
MultipartFiles files;
|
MultipartFiles files;
|
||||||
Match matches;
|
Match matches;
|
||||||
|
|
||||||
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) const;
|
||||||
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) const;
|
||||||
@ -211,10 +215,17 @@ public:
|
|||||||
Client(const char* host, int port, HttpVersion http_version = HttpVersion::v1_0);
|
Client(const char* host, int port, HttpVersion http_version = HttpVersion::v1_0);
|
||||||
virtual ~Client();
|
virtual ~Client();
|
||||||
|
|
||||||
std::shared_ptr<Response> get(const char* path, Progress callback = [](int64_t,int64_t){});
|
std::shared_ptr<Response> get(const char* path, Progress progress = nullptr);
|
||||||
|
std::shared_ptr<Response> get(const char* path, const Headers& headers, Progress progress = nullptr);
|
||||||
|
|
||||||
std::shared_ptr<Response> head(const char* path);
|
std::shared_ptr<Response> head(const char* path);
|
||||||
|
std::shared_ptr<Response> head(const char* path, const Headers& headers);
|
||||||
|
|
||||||
std::shared_ptr<Response> post(const char* path, const std::string& body, const char* content_type);
|
std::shared_ptr<Response> post(const char* path, const std::string& body, const char* content_type);
|
||||||
|
std::shared_ptr<Response> post(const char* path, const Headers& headers, const std::string& body, const char* content_type);
|
||||||
|
|
||||||
std::shared_ptr<Response> post(const char* path, const Params& params);
|
std::shared_ptr<Response> post(const char* path, const Params& params);
|
||||||
|
std::shared_ptr<Response> post(const char* path, const Headers& headers, const Params& params);
|
||||||
|
|
||||||
bool send(const Request& req, Response& res);
|
bool send(const Request& req, Response& res);
|
||||||
|
|
||||||
@ -633,7 +644,9 @@ bool read_content_with_length(Stream& strm, T& x, size_t len, Progress progress)
|
|||||||
if (r_incr <= 0) {
|
if (r_incr <= 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
r += r_incr;
|
r += r_incr;
|
||||||
|
|
||||||
if (progress) {
|
if (progress) {
|
||||||
progress(r, len);
|
progress(r, len);
|
||||||
}
|
}
|
||||||
@ -702,7 +715,7 @@ bool read_content_chunked(Stream& strm, T& x)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool read_content(Stream& strm, T& x, Progress progress = [](int64_t,int64_t){})
|
bool read_content(Stream& strm, T& x, Progress progress = Progress())
|
||||||
{
|
{
|
||||||
auto len = get_header_value_int(x.headers, "Content-Length", 0);
|
auto len = get_header_value_int(x.headers, "Content-Length", 0);
|
||||||
|
|
||||||
@ -980,6 +993,38 @@ inline bool parse_multipart_formdata(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline std::string to_lower(const char* beg, const char* end)
|
||||||
|
{
|
||||||
|
std::string out;
|
||||||
|
auto it = beg;
|
||||||
|
while (it != end) {
|
||||||
|
out += ::tolower(*it);
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void make_range_header_core(std::string&) {}
|
||||||
|
|
||||||
|
template<typename uint64_t>
|
||||||
|
inline void make_range_header_core(std::string& field, uint64_t value)
|
||||||
|
{
|
||||||
|
if (!field.empty()) {
|
||||||
|
field += ", ";
|
||||||
|
}
|
||||||
|
field += std::to_string(value) + "-";
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename uint64_t, typename... Args>
|
||||||
|
inline void make_range_header_core(std::string& field, uint64_t value1, uint64_t value2, Args... args)
|
||||||
|
{
|
||||||
|
if (!field.empty()) {
|
||||||
|
field += ", ";
|
||||||
|
}
|
||||||
|
field += std::to_string(value1) + "-" + std::to_string(value2);
|
||||||
|
make_range_header_core(field, args...);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
class WSInit {
|
class WSInit {
|
||||||
public:
|
public:
|
||||||
@ -996,19 +1041,18 @@ public:
|
|||||||
static WSInit wsinit_;
|
static WSInit wsinit_;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline std::string to_lower(const char* beg, const char* end)
|
|
||||||
{
|
|
||||||
std::string out;
|
|
||||||
auto it = beg;
|
|
||||||
while (it != end) {
|
|
||||||
out += ::tolower(*it);
|
|
||||||
it++;
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
|
// Header utilities
|
||||||
|
template<typename uint64_t, typename... Args>
|
||||||
|
inline std::pair<std::string, std::string> make_range_header(uint64_t value, Args... args)
|
||||||
|
{
|
||||||
|
std::string field;
|
||||||
|
detail::make_range_header_core(field, value, args...);
|
||||||
|
field.insert(0, "bytes=");
|
||||||
|
return std::make_pair("Range", field);
|
||||||
|
}
|
||||||
|
|
||||||
// Request implementation
|
// Request implementation
|
||||||
inline bool Request::has_header(const char* key) const
|
inline bool Request::has_header(const char* key) const
|
||||||
{
|
{
|
||||||
@ -1020,11 +1064,6 @@ inline std::string Request::get_header_value(const char* key) const
|
|||||||
return detail::get_header_value(headers, key, "");
|
return detail::get_header_value(headers, key, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Request::set_header(const char* key, const char* val)
|
|
||||||
{
|
|
||||||
headers.emplace(key, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool Request::has_param(const char* key) const
|
inline bool Request::has_param(const char* key) const
|
||||||
{
|
{
|
||||||
return params.find(key) != params.end();
|
return params.find(key) != params.end();
|
||||||
@ -1485,12 +1524,18 @@ inline bool Client::read_and_close_socket(socket_t sock, const Request& req, Res
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::shared_ptr<Response> Client::get(const char* path, Progress callback)
|
inline std::shared_ptr<Response> Client::get(const char* path, Progress progress)
|
||||||
|
{
|
||||||
|
return get(path, Headers(), progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::shared_ptr<Response> Client::get(const char* path, const Headers& headers, Progress progress)
|
||||||
{
|
{
|
||||||
Request req;
|
Request req;
|
||||||
req.method = "GET";
|
req.method = "GET";
|
||||||
req.path = path;
|
req.path = path;
|
||||||
req.progress = callback;
|
req.headers = headers;
|
||||||
|
req.progress = progress;
|
||||||
|
|
||||||
auto res = std::make_shared<Response>();
|
auto res = std::make_shared<Response>();
|
||||||
|
|
||||||
@ -1498,9 +1543,15 @@ inline std::shared_ptr<Response> Client::get(const char* path, Progress callback
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline std::shared_ptr<Response> Client::head(const char* path)
|
inline std::shared_ptr<Response> Client::head(const char* path)
|
||||||
|
{
|
||||||
|
return head(path, Headers());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::shared_ptr<Response> Client::head(const char* path, const Headers& headers)
|
||||||
{
|
{
|
||||||
Request req;
|
Request req;
|
||||||
req.method = "HEAD";
|
req.method = "HEAD";
|
||||||
|
req.headers = headers;
|
||||||
req.path = path;
|
req.path = path;
|
||||||
|
|
||||||
auto res = std::make_shared<Response>();
|
auto res = std::make_shared<Response>();
|
||||||
@ -1510,12 +1561,19 @@ inline std::shared_ptr<Response> Client::head(const char* path)
|
|||||||
|
|
||||||
inline std::shared_ptr<Response> Client::post(
|
inline std::shared_ptr<Response> Client::post(
|
||||||
const char* path, const std::string& body, const char* content_type)
|
const char* path, const std::string& body, const char* content_type)
|
||||||
|
{
|
||||||
|
return post(path, Headers(), body, content_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::shared_ptr<Response> Client::post(
|
||||||
|
const char* path, const Headers& headers, const std::string& body, const char* content_type)
|
||||||
{
|
{
|
||||||
Request req;
|
Request req;
|
||||||
req.method = "POST";
|
req.method = "POST";
|
||||||
|
req.headers = headers;
|
||||||
req.path = path;
|
req.path = path;
|
||||||
|
|
||||||
req.set_header("Content-Type", content_type);
|
req.headers.emplace("Content-Type", content_type);
|
||||||
req.body = body;
|
req.body = body;
|
||||||
|
|
||||||
auto res = std::make_shared<Response>();
|
auto res = std::make_shared<Response>();
|
||||||
@ -1523,8 +1581,12 @@ inline std::shared_ptr<Response> Client::post(
|
|||||||
return send(req, *res) ? res : nullptr;
|
return send(req, *res) ? res : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::shared_ptr<Response> Client::post(
|
inline std::shared_ptr<Response> Client::post(const char* path, const Params& params)
|
||||||
const char* path, const Params& params)
|
{
|
||||||
|
return post(path, Headers(), params);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::shared_ptr<Response> Client::post(const char* path, const Headers& headers, const Params& params)
|
||||||
{
|
{
|
||||||
std::string query;
|
std::string query;
|
||||||
for (auto it = params.begin(); it != params.end(); ++it) {
|
for (auto it = params.begin(); it != params.end(); ++it) {
|
||||||
@ -1536,7 +1598,7 @@ inline std::shared_ptr<Response> Client::post(
|
|||||||
query += it->second;
|
query += it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
return post(path, query, "application/x-www-form-urlencoded");
|
return post(path, headers, query, "application/x-www-form-urlencoded");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
107
test/test.cc
107
test/test.cc
@ -83,32 +83,59 @@ TEST(SocketTest, OpenCloseWithAI_PASSIVE)
|
|||||||
|
|
||||||
TEST(GetHeaderValueTest, DefaultValue)
|
TEST(GetHeaderValueTest, DefaultValue)
|
||||||
{
|
{
|
||||||
Headers map = {{"Dummy","Dummy"}};
|
Headers headers = {{"Dummy","Dummy"}};
|
||||||
auto val = detail::get_header_value(map, "Content-Type", "text/plain");
|
auto val = detail::get_header_value(headers, "Content-Type", "text/plain");
|
||||||
ASSERT_STREQ("text/plain", val);
|
EXPECT_STREQ("text/plain", val);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(GetHeaderValueTest, DefaultValueInt)
|
TEST(GetHeaderValueTest, DefaultValueInt)
|
||||||
{
|
{
|
||||||
Headers map = {{"Dummy","Dummy"}};
|
Headers headers = {{"Dummy","Dummy"}};
|
||||||
auto val = detail::get_header_value_int(map, "Content-Length", 100);
|
auto val = detail::get_header_value_int(headers, "Content-Length", 100);
|
||||||
EXPECT_EQ(100, val);
|
EXPECT_EQ(100, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(GetHeaderValueTest, RegularValue)
|
TEST(GetHeaderValueTest, RegularValue)
|
||||||
{
|
{
|
||||||
Headers map = {{"Content-Type", "text/html"}, {"Dummy", "Dummy"}};
|
Headers headers = {{"Content-Type", "text/html"}, {"Dummy", "Dummy"}};
|
||||||
auto val = detail::get_header_value(map, "Content-Type", "text/plain");
|
auto val = detail::get_header_value(headers, "Content-Type", "text/plain");
|
||||||
ASSERT_STREQ("text/html", val);
|
EXPECT_STREQ("text/html", val);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(GetHeaderValueTest, RegularValueInt)
|
TEST(GetHeaderValueTest, RegularValueInt)
|
||||||
{
|
{
|
||||||
Headers map = {{"Content-Length", "100"}, {"Dummy", "Dummy"}};
|
Headers headers = {{"Content-Length", "100"}, {"Dummy", "Dummy"}};
|
||||||
auto val = detail::get_header_value_int(map, "Content-Length", 0);
|
auto val = detail::get_header_value_int(headers, "Content-Length", 0);
|
||||||
EXPECT_EQ(100, val);
|
EXPECT_EQ(100, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(GetHeaderValueTest, Range)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
Headers headers = { make_range_header(1) };
|
||||||
|
auto val = detail::get_header_value(headers, "Range", 0);
|
||||||
|
EXPECT_STREQ("bytes=1-", val);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Headers headers = { make_range_header(1, 10) };
|
||||||
|
auto val = detail::get_header_value(headers, "Range", 0);
|
||||||
|
EXPECT_STREQ("bytes=1-10", val);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Headers headers = { make_range_header(1, 10, 100) };
|
||||||
|
auto val = detail::get_header_value(headers, "Range", 0);
|
||||||
|
EXPECT_STREQ("bytes=1-10, 100-", val);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Headers headers = { make_range_header(1, 10, 100, 200) };
|
||||||
|
auto val = detail::get_header_value(headers, "Range", 0);
|
||||||
|
EXPECT_STREQ("bytes=1-10, 100-200", val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void testChunkedEncoding(httplib::HttpVersion ver)
|
void testChunkedEncoding(httplib::HttpVersion ver)
|
||||||
{
|
{
|
||||||
auto host = "www.httpwatch.com";
|
auto host = "www.httpwatch.com";
|
||||||
@ -136,6 +163,42 @@ TEST(ChunkedEncodingTest, FromHTTPWatch)
|
|||||||
testChunkedEncoding(httplib::HttpVersion::v1_1);
|
testChunkedEncoding(httplib::HttpVersion::v1_1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(RangeTest, FromHTTPBin)
|
||||||
|
{
|
||||||
|
auto host = "httpbin.org";
|
||||||
|
auto port = 80;
|
||||||
|
|
||||||
|
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||||
|
httplib::SSLClient cli(host, port, httplib::HttpVersion::v1_1);
|
||||||
|
#else
|
||||||
|
httplib::Client cli(host, port, httplib::HttpVersion::v1_1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{
|
||||||
|
httplib::Headers headers;
|
||||||
|
auto res = cli.get("/range/32", headers);
|
||||||
|
ASSERT_TRUE(res != nullptr);
|
||||||
|
EXPECT_EQ(res->body, "abcdefghijklmnopqrstuvwxyzabcdef");
|
||||||
|
EXPECT_EQ(200, res->status);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
httplib::Headers headers = { httplib::make_range_header(1) };
|
||||||
|
auto res = cli.get("/range/32", headers);
|
||||||
|
ASSERT_TRUE(res != nullptr);
|
||||||
|
EXPECT_EQ(res->body, "bcdefghijklmnopqrstuvwxyzabcdef");
|
||||||
|
EXPECT_EQ(206, res->status);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
httplib::Headers headers = { httplib::make_range_header(1, 10) };
|
||||||
|
auto res = cli.get("/range/32", headers);
|
||||||
|
ASSERT_TRUE(res != nullptr);
|
||||||
|
EXPECT_EQ(res->body, "bcdefghijk");
|
||||||
|
EXPECT_EQ(206, res->status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ServerTest : public ::testing::Test {
|
class ServerTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
ServerTest()
|
ServerTest()
|
||||||
@ -422,11 +485,11 @@ TEST_F(ServerTest, LongHeader)
|
|||||||
host_and_port += ":";
|
host_and_port += ":";
|
||||||
host_and_port += std::to_string(PORT);
|
host_and_port += std::to_string(PORT);
|
||||||
|
|
||||||
req.set_header("Host", host_and_port.c_str());
|
req.headers.emplace("Host", host_and_port.c_str());
|
||||||
req.set_header("Accept", "*/*");
|
req.headers.emplace("Accept", "*/*");
|
||||||
req.set_header("User-Agent", "cpp-httplib/0.1");
|
req.headers.emplace("User-Agent", "cpp-httplib/0.1");
|
||||||
|
|
||||||
req.set_header("Header-Name", "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
req.headers.emplace("Header-Name", "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
||||||
|
|
||||||
auto res = std::make_shared<Response>();
|
auto res = std::make_shared<Response>();
|
||||||
auto ret = cli_.send(req, *res);
|
auto ret = cli_.send(req, *res);
|
||||||
@ -446,11 +509,11 @@ TEST_F(ServerTest, TooLongHeader)
|
|||||||
host_and_port += ":";
|
host_and_port += ":";
|
||||||
host_and_port += std::to_string(PORT);
|
host_and_port += std::to_string(PORT);
|
||||||
|
|
||||||
req.set_header("Host", host_and_port.c_str());
|
req.headers.emplace("Host", host_and_port.c_str());
|
||||||
req.set_header("Accept", "*/*");
|
req.headers.emplace("Accept", "*/*");
|
||||||
req.set_header("User-Agent", "cpp-httplib/0.1");
|
req.headers.emplace("User-Agent", "cpp-httplib/0.1");
|
||||||
|
|
||||||
req.set_header("Header-Name", "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
req.headers.emplace("Header-Name", "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
||||||
|
|
||||||
auto res = std::make_shared<Response>();
|
auto res = std::make_shared<Response>();
|
||||||
auto ret = cli_.send(req, *res);
|
auto ret = cli_.send(req, *res);
|
||||||
@ -498,10 +561,10 @@ TEST_F(ServerTest, MultipartFormData)
|
|||||||
host_and_port += ":";
|
host_and_port += ":";
|
||||||
host_and_port += std::to_string(PORT);
|
host_and_port += std::to_string(PORT);
|
||||||
|
|
||||||
req.set_header("Host", host_and_port.c_str());
|
req.headers.emplace("Host", host_and_port.c_str());
|
||||||
req.set_header("Accept", "*/*");
|
req.headers.emplace("Accept", "*/*");
|
||||||
req.set_header("User-Agent", "cpp-httplib/0.1");
|
req.headers.emplace("User-Agent", "cpp-httplib/0.1");
|
||||||
req.set_header("Content-Type", "multipart/form-data; boundary=----WebKitFormBoundarysBREP3G013oUrLB4");
|
req.headers.emplace("Content-Type", "multipart/form-data; boundary=----WebKitFormBoundarysBREP3G013oUrLB4");
|
||||||
|
|
||||||
req.body = "------WebKitFormBoundarysBREP3G013oUrLB4\r\nContent-Disposition: form-data; name=\"text1\"\r\n\r\ntext default\r\n------WebKitFormBoundarysBREP3G013oUrLB4\r\nContent-Disposition: form-data; name=\"text2\"\r\n\r\naωb\r\n------WebKitFormBoundarysBREP3G013oUrLB4\r\nContent-Disposition: form-data; name=\"file1\"; filename=\"hello.txt\"\r\nContent-Type: text/plain\r\n\r\nh\ne\n\nl\nl\no\n\r\n------WebKitFormBoundarysBREP3G013oUrLB4\r\nContent-Disposition: form-data; name=\"file2\"; filename=\"world.json\"\r\nContent-Type: application/json\r\n\r\n{\n \"world\", true\n}\n\r\n------WebKitFormBoundarysBREP3G013oUrLB4\r\nContent-Disposition: form-data; name=\"file3\"; filename=\"\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n------WebKitFormBoundarysBREP3G013oUrLB4--\r\n";
|
req.body = "------WebKitFormBoundarysBREP3G013oUrLB4\r\nContent-Disposition: form-data; name=\"text1\"\r\n\r\ntext default\r\n------WebKitFormBoundarysBREP3G013oUrLB4\r\nContent-Disposition: form-data; name=\"text2\"\r\n\r\naωb\r\n------WebKitFormBoundarysBREP3G013oUrLB4\r\nContent-Disposition: form-data; name=\"file1\"; filename=\"hello.txt\"\r\nContent-Type: text/plain\r\n\r\nh\ne\n\nl\nl\no\n\r\n------WebKitFormBoundarysBREP3G013oUrLB4\r\nContent-Disposition: form-data; name=\"file2\"; filename=\"world.json\"\r\nContent-Type: application/json\r\n\r\n{\n \"world\", true\n}\n\r\n------WebKitFormBoundarysBREP3G013oUrLB4\r\nContent-Disposition: form-data; name=\"file3\"; filename=\"\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n------WebKitFormBoundarysBREP3G013oUrLB4--\r\n";
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user