Skip to content

Commit bea3ebd

Browse files
committed
Added 'compress' option to POST, PUT and PATCH.
1 parent 380f725 commit bea3ebd

File tree

2 files changed

+69
-92
lines changed

2 files changed

+69
-92
lines changed

httplib.h

Lines changed: 63 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -589,36 +589,37 @@ class Client {
589589
std::shared_ptr<Response> Head(const char *path, const Headers &headers);
590590

591591
std::shared_ptr<Response> Post(const char *path, const std::string &body,
592-
const char *content_type);
592+
const char *content_type, bool compress = false);
593593

594594
std::shared_ptr<Response> Post(const char *path, const Headers &headers,
595595
const std::string &body,
596-
const char *content_type);
596+
const char *content_type,
597+
bool compress = false);
597598

598-
std::shared_ptr<Response> Post(const char *path, const Params &params);
599+
std::shared_ptr<Response> Post(const char *path, const Params &params, bool compress = false);
599600

600601
std::shared_ptr<Response> Post(const char *path, const Headers &headers,
601-
const Params &params);
602+
const Params &params, bool compress = false);
602603

603604
std::shared_ptr<Response> Post(const char *path,
604-
const MultipartFormDataItems &items);
605+
const MultipartFormDataItems &items, bool compress = false);
605606

606607
std::shared_ptr<Response> Post(const char *path, const Headers &headers,
607-
const MultipartFormDataItems &items);
608+
const MultipartFormDataItems &items, bool compress = false);
608609

609610
std::shared_ptr<Response> Put(const char *path, const std::string &body,
610-
const char *content_type);
611+
const char *content_type, bool compress = false);
611612

612613
std::shared_ptr<Response> Put(const char *path, const Headers &headers,
613614
const std::string &body,
614-
const char *content_type);
615+
const char *content_type, bool compress = false);
615616

616617
std::shared_ptr<Response> Patch(const char *path, const std::string &body,
617-
const char *content_type);
618+
const char *content_type, bool compress = false);
618619

619620
std::shared_ptr<Response> Patch(const char *path, const Headers &headers,
620621
const std::string &body,
621-
const char *content_type);
622+
const char *content_type, bool compress = false);
622623

623624
std::shared_ptr<Response> Delete(const char *path);
624625

@@ -3119,14 +3120,14 @@ inline std::shared_ptr<Response> Client::Head(const char *path,
31193120

31203121
inline std::shared_ptr<Response> Client::Post(const char *path,
31213122
const std::string &body,
3122-
const char *content_type) {
3123-
return Post(path, Headers(), body, content_type);
3123+
const char *content_type, bool compress) {
3124+
return Post(path, Headers(), body, content_type, compress);
31243125
}
31253126

31263127
inline std::shared_ptr<Response> Client::Post(const char *path,
31273128
const Headers &headers,
31283129
const std::string &body,
3129-
const char *content_type) {
3130+
const char *content_type, bool compress) {
31303131
Request req;
31313132
req.method = "POST";
31323133
req.headers = headers;
@@ -3135,18 +3136,25 @@ inline std::shared_ptr<Response> Client::Post(const char *path,
31353136
req.headers.emplace("Content-Type", content_type);
31363137
req.body = body;
31373138

3139+
if (compress) {
3140+
if (!detail::compress(req.body)) {
3141+
return nullptr;
3142+
}
3143+
req.headers.emplace("Content-Encoding", "gzip");
3144+
}
3145+
31383146
auto res = std::make_shared<Response>();
31393147

31403148
return send(req, *res) ? res : nullptr;
31413149
}
31423150

31433151
inline std::shared_ptr<Response> Client::Post(const char *path,
3144-
const Params &params) {
3145-
return Post(path, Headers(), params);
3152+
const Params &params, bool compress) {
3153+
return Post(path, Headers(), params, compress);
31463154
}
31473155

31483156
inline std::shared_ptr<Response>
3149-
Client::Post(const char *path, const Headers &headers, const Params &params) {
3157+
Client::Post(const char *path, const Headers &headers, const Params &params, bool compress) {
31503158
std::string query;
31513159
for (auto it = params.begin(); it != params.end(); ++it) {
31523160
if (it != params.begin()) { query += "&"; }
@@ -3155,58 +3163,53 @@ Client::Post(const char *path, const Headers &headers, const Params &params) {
31553163
query += detail::encode_url(it->second);
31563164
}
31573165

3158-
return Post(path, headers, query, "application/x-www-form-urlencoded");
3166+
return Post(path, headers, query, "application/x-www-form-urlencoded", compress);
31593167
}
31603168

31613169
inline std::shared_ptr<Response>
3162-
Client::Post(const char *path, const MultipartFormDataItems &items) {
3163-
return Post(path, Headers(), items);
3170+
Client::Post(const char *path, const MultipartFormDataItems &items, bool compress) {
3171+
return Post(path, Headers(), items, compress);
31643172
}
31653173

31663174
inline std::shared_ptr<Response>
31673175
Client::Post(const char *path, const Headers &headers,
3168-
const MultipartFormDataItems &items) {
3169-
Request req;
3170-
req.method = "POST";
3171-
req.headers = headers;
3172-
req.path = path;
3173-
3176+
const MultipartFormDataItems &items, bool compress) {
31743177
auto boundary = detail::make_multipart_data_boundary();
31753178

3176-
req.headers.emplace("Content-Type",
3177-
"multipart/form-data; boundary=" + boundary);
3179+
std::string body;
31783180

31793181
for (const auto &item : items) {
3180-
req.body += "--" + boundary + "\r\n";
3181-
req.body += "Content-Disposition: form-data; name=\"" + item.name + "\"";
3182+
body += "--" + boundary + "\r\n";
3183+
body += "Content-Disposition: form-data; name=\"" + item.name + "\"";
31823184
if (!item.filename.empty()) {
3183-
req.body += "; filename=\"" + item.filename + "\"";
3185+
body += "; filename=\"" + item.filename + "\"";
31843186
}
3185-
req.body += "\r\n";
3187+
body += "\r\n";
31863188
if (!item.content_type.empty()) {
3187-
req.body += "Content-Type: " + item.content_type + "\r\n";
3189+
body += "Content-Type: " + item.content_type + "\r\n";
31883190
}
3189-
req.body += "\r\n";
3190-
req.body += item.content + "\r\n";
3191+
body += "\r\n";
3192+
body += item.content + "\r\n";
31913193
}
31923194

3193-
req.body += "--" + boundary + "--\r\n";
3195+
body += "--" + boundary + "--\r\n";
31943196

3195-
auto res = std::make_shared<Response>();
3196-
3197-
return send(req, *res) ? res : nullptr;
3197+
std::string content_type = "multipart/form-data; boundary=" + boundary;
3198+
return Post(path, headers, body, content_type.c_str(), compress);
31983199
}
31993200

32003201
inline std::shared_ptr<Response> Client::Put(const char *path,
32013202
const std::string &body,
3202-
const char *content_type) {
3203-
return Put(path, Headers(), body, content_type);
3203+
const char *content_type,
3204+
bool compress) {
3205+
return Put(path, Headers(), body, content_type, compress);
32043206
}
32053207

32063208
inline std::shared_ptr<Response> Client::Put(const char *path,
32073209
const Headers &headers,
32083210
const std::string &body,
3209-
const char *content_type) {
3211+
const char *content_type,
3212+
bool compress) {
32103213
Request req;
32113214
req.method = "PUT";
32123215
req.headers = headers;
@@ -3215,21 +3218,30 @@ inline std::shared_ptr<Response> Client::Put(const char *path,
32153218
req.headers.emplace("Content-Type", content_type);
32163219
req.body = body;
32173220

3221+
if (compress) {
3222+
if (!detail::compress(req.body)) {
3223+
return nullptr;
3224+
}
3225+
req.headers.emplace("Content-Encoding", "gzip");
3226+
}
3227+
32183228
auto res = std::make_shared<Response>();
32193229

32203230
return send(req, *res) ? res : nullptr;
32213231
}
32223232

32233233
inline std::shared_ptr<Response> Client::Patch(const char *path,
32243234
const std::string &body,
3225-
const char *content_type) {
3226-
return Patch(path, Headers(), body, content_type);
3235+
const char *content_type,
3236+
bool compress) {
3237+
return Patch(path, Headers(), body, content_type, compress);
32273238
}
32283239

32293240
inline std::shared_ptr<Response> Client::Patch(const char *path,
32303241
const Headers &headers,
32313242
const std::string &body,
3232-
const char *content_type) {
3243+
const char *content_type,
3244+
bool compress) {
32333245
Request req;
32343246
req.method = "PATCH";
32353247
req.headers = headers;
@@ -3238,6 +3250,13 @@ inline std::shared_ptr<Response> Client::Patch(const char *path,
32383250
req.headers.emplace("Content-Type", content_type);
32393251
req.body = body;
32403252

3253+
if (compress) {
3254+
if (!detail::compress(req.body)) {
3255+
return nullptr;
3256+
}
3257+
req.headers.emplace("Content-Encoding", "gzip");
3258+
}
3259+
32413260
auto res = std::make_shared<Response>();
32423261

32433262
return send(req, *res) ? res : nullptr;

test/test.cc

Lines changed: 6 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1549,56 +1549,14 @@ TEST_F(ServerTest, NoGzipWithContentReceiver) {
15491549
}
15501550

15511551
TEST_F(ServerTest, MultipartFormDataGzip) {
1552-
Request req;
1553-
req.method = "POST";
1554-
req.path = "/gzipmultipart";
1555-
1556-
std::string host_and_port;
1557-
host_and_port += HOST;
1558-
host_and_port += ":";
1559-
host_and_port += std::to_string(PORT);
1560-
1561-
req.headers.emplace("Host", host_and_port.c_str());
1562-
req.headers.emplace("Accept", "*/*");
1563-
req.headers.emplace("User-Agent", "cpp-httplib/0.1");
1564-
req.headers.emplace(
1565-
"Content-Type",
1566-
"multipart/form-data; boundary=------------------------fcba8368a9f48c0f");
1567-
req.headers.emplace("Content-Encoding", "gzip");
1568-
1569-
// compressed_body generated by creating input.txt to this file:
1570-
/*
1571-
--------------------------fcba8368a9f48c0f
1572-
Content-Disposition: form-data; name="key1"
1573-
1574-
test
1575-
--------------------------fcba8368a9f48c0f
1576-
Content-Disposition: form-data; name="key2"
1577-
1578-
--abcdefg123
1579-
--------------------------fcba8368a9f48c0f--
1580-
*/
1581-
// then running unix2dos input.txt; gzip -9 -c input.txt | xxd -i.
1582-
uint8_t compressed_body[] = {
1583-
0x1f, 0x8b, 0x08, 0x08, 0x48, 0xf1, 0xd4, 0x5a, 0x02, 0x03, 0x69, 0x6e,
1584-
0x70, 0x75, 0x74, 0x2e, 0x74, 0x78, 0x74, 0x00, 0xd3, 0xd5, 0xc5, 0x05,
1585-
0xd2, 0x92, 0x93, 0x12, 0x2d, 0x8c, 0xcd, 0x2c, 0x12, 0x2d, 0xd3, 0x4c,
1586-
0x2c, 0x92, 0x0d, 0xd2, 0x78, 0xb9, 0x9c, 0xf3, 0xf3, 0x4a, 0x52, 0xf3,
1587-
0x4a, 0x74, 0x5d, 0x32, 0x8b, 0x0b, 0xf2, 0x8b, 0x33, 0x4b, 0x32, 0xf3,
1588-
0xf3, 0xac, 0x14, 0xd2, 0xf2, 0x8b, 0x72, 0x75, 0x53, 0x12, 0x4b, 0x12,
1589-
0xad, 0x15, 0xf2, 0x12, 0x73, 0x53, 0x6d, 0x95, 0xb2, 0x53, 0x2b, 0x0d,
1590-
0x95, 0x78, 0xb9, 0x78, 0xb9, 0x4a, 0x52, 0x8b, 0x4b, 0x78, 0xb9, 0x74,
1591-
0x69, 0x61, 0x81, 0x11, 0xd8, 0x02, 0x5d, 0xdd, 0xc4, 0xa4, 0xe4, 0x94,
1592-
0xd4, 0xb4, 0x74, 0x43, 0x23, 0x63, 0x52, 0x2c, 0xd2, 0xd5, 0xe5, 0xe5,
1593-
0x02, 0x00, 0xff, 0x0e, 0x72, 0xdf, 0xf8, 0x00, 0x00, 0x00};
1594-
1595-
req.body = std::string((char *)compressed_body,
1596-
sizeof(compressed_body) / sizeof(compressed_body[0]));
1552+
MultipartFormDataItems items = {
1553+
{"key1", "test", "", ""},
1554+
{"key2", "--abcdefg123", "", ""},
1555+
};
15971556

1598-
auto res = std::make_shared<Response>();
1599-
auto ret = cli_.send(req, *res);
1557+
auto res = cli_.Post("/gzipmultipart", items, true);
16001558

1601-
ASSERT_TRUE(ret);
1559+
ASSERT_TRUE(res != nullptr);
16021560
EXPECT_EQ(200, res->status);
16031561
}
16041562
#endif

0 commit comments

Comments
 (0)