Don't fail chunked read if buffer not yet filled

This commit is contained in:
Scott Graham 2018-04-17 22:02:24 -07:00
parent 956faae6f0
commit 889041f05f
2 changed files with 37 additions and 4 deletions

View file

@ -817,10 +817,8 @@ bool read_content_chunked(Stream& strm, std::string& out)
auto chunk_len = std::stoi(reader.ptr(), 0, 16);
while (chunk_len > 0){
std::string chunk(chunk_len, 0);
auto n = strm.read(&chunk[0], chunk_len);
if (n <= 0) {
std::string chunk;
if (!read_content_with_length(strm, chunk, chunk_len, nullptr)) {
return false;
}

View file

@ -295,6 +295,10 @@ protected:
.post("/chunked", [&](const Request& req, Response& /*res*/) {
EXPECT_EQ(req.body, "dechunked post body");
})
.post("/largechunked", [&](const Request& req, Response& /*res*/) {
std::string expected(6 * 30 * 1024u, 'a');
EXPECT_EQ(req.body, expected);
})
.post("/multipart", [&](const Request& req, Response& /*res*/) {
EXPECT_EQ(5u, req.files.size());
ASSERT_TRUE(!req.has_file("???"));
@ -690,6 +694,37 @@ TEST_F(ServerTest, CaseInsensitiveTransferEncoding)
EXPECT_EQ(200, res->status);
}
TEST_F(ServerTest, LargeChunkedPost) {
Request req;
req.method = "POST";
req.path = "/largechunked";
std::string host_and_port;
host_and_port += HOST;
host_and_port += ":";
host_and_port += std::to_string(PORT);
req.headers.emplace("Host", host_and_port.c_str());
req.headers.emplace("Accept", "*/*");
req.headers.emplace("User-Agent", "cpp-httplib/0.1");
req.headers.emplace("Content-Type", "text/plain");
req.headers.emplace("Content-Length", "0");
req.headers.emplace("Transfer-Encoding", "chunked");
std::string long_string(30 * 1024u, 'a');
std::string chunk = "7800\r\n" + long_string + "\r\n";
// Attempt to make a large enough post to exceed OS buffers, to test that
// the server handles short reads if the full chunk data isn't available.
req.body = chunk + chunk + chunk + chunk + chunk + chunk + "0\r\n\r\n";
auto res = std::make_shared<Response>();
auto ret = cli_.send(req, *res);
ASSERT_TRUE(ret);
EXPECT_EQ(200, res->status);
}
TEST_F(ServerTest, GetMethodRemoteAddr)
{
auto res = cli_.get("/remote_addr");