Compare commits

..

5 Commits

Author SHA1 Message Date
rymis f2bb9c45d6 Support for deflate compression (#360) 2020-02-24 11:48:00 -05:00
yhirose 9a663aa94e Added a unit test. 2020-02-21 11:48:47 -05:00
yhirose d0d744d520 Fixed compiler warning with Visual C++. Close #358 2020-02-20 17:30:04 -05:00
yhirose fce8e6fefd Merge pull request #356 from samhocevar/fix-shadow-declarations
Fix a few shadowed variable compilation warnings.
2020-02-17 09:01:47 -05:00
Sam Hocevar 180aa32ebf Fix a few shadowed variable compilation warnings. 2020-02-17 06:58:30 +01:00
2 changed files with 51 additions and 24 deletions
+28 -24
View File
@@ -1545,7 +1545,8 @@ inline std::string get_remote_addr(socket_t sock) {
std::array<char, NI_MAXHOST> ipstr{};
if (!getnameinfo(reinterpret_cast<struct sockaddr *>(&addr), len,
ipstr.data(), ipstr.size(), nullptr, 0, NI_NUMERICHOST)) {
ipstr.data(), static_cast<socklen_t>(ipstr.size()),
nullptr, 0, NI_NUMERICHOST)) {
return ipstr.data();
}
}
@@ -1666,14 +1667,15 @@ inline bool compress(std::string &content) {
class decompressor {
public:
decompressor() {
std::memset(&strm, 0, sizeof(strm));
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
// 15 is the value of wbits, which should be at the maximum possible value
// to ensure that any gzip stream can be decoded. The offset of 16 specifies
// that the stream to decompress will be formatted with a gzip wrapper.
is_valid_ = inflateInit2(&strm, 16 + 15) == Z_OK;
// to ensure that any gzip stream can be decoded. The offset of 32 specifies
// that the stream type should be automatically detected either gzip or deflate.
is_valid_ = inflateInit2(&strm, 32 + 15) == Z_OK;
}
~decompressor() { inflateEnd(&strm); }
@@ -1871,12 +1873,14 @@ bool read_content(Stream &strm, T &x, size_t payload_max_length, int &status,
#ifdef CPPHTTPLIB_ZLIB_SUPPORT
decompressor decompressor;
if (!decompressor.is_valid()) {
status = 500;
return false;
}
std::string content_encoding = x.get_header_value("Content-Encoding");
if (content_encoding.find("gzip") != std::string::npos
|| content_encoding.find("deflate") != std::string::npos) {
if (!decompressor.is_valid()) {
status = 500;
return false;
}
if (x.get_header_value("Content-Encoding") == "gzip") {
out = [&](const char *buf, size_t n) {
return decompressor.decompress(
buf, n, [&](const char *buf, size_t n) { return receiver(buf, n); });
@@ -2072,11 +2076,11 @@ inline void parse_query_text(const std::string &s, Params &params) {
split(&s[0], &s[s.size()], '&', [&](const char *b, const char *e) {
std::string key;
std::string val;
split(b, e, '=', [&](const char *b, const char *e) {
split(b, e, '=', [&](const char *b2, const char *e2) {
if (key.empty()) {
key.assign(b, e);
key.assign(b2, e2);
} else {
val.assign(b, e);
val.assign(b2, e2);
}
});
params.emplace(key, decode_url(val));
@@ -2102,16 +2106,16 @@ inline bool parse_range_header(const std::string &s, Ranges &ranges) {
split(&s[pos], &s[pos + len], ',', [&](const char *b, const char *e) {
if (!all_valid_ranges) return;
static auto re_another_range = std::regex(R"(\s*(\d*)-(\d*))");
std::cmatch m;
if (std::regex_match(b, e, m, re_another_range)) {
std::cmatch cm;
if (std::regex_match(b, e, cm, re_another_range)) {
ssize_t first = -1;
if (!m.str(1).empty()) {
first = static_cast<ssize_t>(std::stoll(m.str(1)));
if (!cm.str(1).empty()) {
first = static_cast<ssize_t>(std::stoll(cm.str(1)));
}
ssize_t last = -1;
if (!m.str(2).empty()) {
last = static_cast<ssize_t>(std::stoll(m.str(2)));
if (!cm.str(2).empty()) {
last = static_cast<ssize_t>(std::stoll(cm.str(2)));
}
if (first != -1 && last != -1 && first > last) {
@@ -2579,10 +2583,10 @@ inline std::pair<std::string, std::string> make_digest_authentication_header(
inline bool parse_www_authenticate(const httplib::Response &res,
std::map<std::string, std::string> &auth,
bool is_proxy) {
auto key = is_proxy ? "Proxy-Authenticate" : "WWW-Authenticate";
if (res.has_header(key)) {
auto auth_key = is_proxy ? "Proxy-Authenticate" : "WWW-Authenticate";
if (res.has_header(auth_key)) {
static auto re = std::regex(R"~((?:(?:,\s*)?(.+?)=(?:"(.*?)"|([^,]*))))~");
auto s = res.get_header_value(key);
auto s = res.get_header_value(auth_key);
auto pos = s.find(' ');
if (pos != std::string::npos) {
auto type = s.substr(0, pos);
@@ -2713,11 +2717,11 @@ inline void Response::set_content(const std::string &s,
}
inline void Response::set_content_provider(
size_t length,
size_t in_length,
std::function<void(size_t offset, size_t length, DataSink &sink)> provider,
std::function<void()> resource_releaser) {
assert(length > 0);
content_length = length;
assert(in_length > 0);
content_length = in_length;
content_provider = [provider](size_t offset, size_t length, DataSink &sink) {
provider(offset, length, sink);
};
+23
View File
@@ -1041,6 +1041,16 @@ TEST_F(ServerTest, GetMethod200) {
EXPECT_EQ("Hello World!", res->body);
}
TEST_F(ServerTest, GetMethod200withPercentEncoding) {
auto res = cli_.Get("/%68%69"); // auto res = cli_.Get("/hi");
ASSERT_TRUE(res != nullptr);
EXPECT_EQ("HTTP/1.1", res->version);
EXPECT_EQ(200, res->status);
EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
EXPECT_EQ(1, res->get_header_value_count("Content-Type"));
EXPECT_EQ("Hello World!", res->body);
}
TEST_F(ServerTest, GetMethod302) {
auto res = cli_.Get("/");
ASSERT_TRUE(res != nullptr);
@@ -1695,6 +1705,19 @@ TEST_F(ServerTest, PutLargeFileWithGzip) {
EXPECT_EQ(200, res->status);
EXPECT_EQ(LARGE_DATA, res->body);
}
TEST_F(ServerTest, PutContentWithDeflate) {
cli_.set_compress(false);
httplib::Headers headers;
headers.emplace("Content-Encoding", "deflate");
// PUT in deflate format:
auto res = cli_.Put("/put", headers, "\170\234\013\010\015\001\0\001\361\0\372", "text/plain");
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(200, res->status);
EXPECT_EQ("PUT", res->body);
}
#endif
TEST_F(ServerTest, Patch) {