mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2025-05-10 01:33:53 +00:00
* fix: skip MIME preamble (#1317) * Skip epilogue in multipart/form-data Co-authored-by: Gavin1937 <71205842+Gavin1937@users.noreply.github.com>
This commit is contained in:
parent
caa31aafda
commit
127a64d5a0
@ -3794,6 +3794,7 @@ public:
|
|||||||
switch (state_) {
|
switch (state_) {
|
||||||
case 0: { // Initial boundary
|
case 0: { // Initial boundary
|
||||||
auto pattern = dash_ + boundary_ + crlf_;
|
auto pattern = dash_ + boundary_ + crlf_;
|
||||||
|
buf_erase(buf_find(pattern));
|
||||||
if (pattern.size() > buf_size()) { return true; }
|
if (pattern.size() > buf_size()) { return true; }
|
||||||
if (!buf_start_with(pattern)) { return false; }
|
if (!buf_start_with(pattern)) { return false; }
|
||||||
buf_erase(pattern.size());
|
buf_erase(pattern.size());
|
||||||
@ -3887,17 +3888,13 @@ public:
|
|||||||
if (buf_start_with(pattern)) {
|
if (buf_start_with(pattern)) {
|
||||||
buf_erase(pattern.size());
|
buf_erase(pattern.size());
|
||||||
is_valid_ = true;
|
is_valid_ = true;
|
||||||
state_ = 5;
|
buf_erase(buf_size()); // Remove epilogue
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 5: { // Done
|
|
||||||
is_valid_ = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
56
test/test.cc
56
test/test.cc
@ -3015,8 +3015,10 @@ TEST(GzipDecompressor, ChunkedDecompression) {
|
|||||||
httplib::detail::gzip_compressor compressor;
|
httplib::detail::gzip_compressor compressor;
|
||||||
bool result = compressor.compress(
|
bool result = compressor.compress(
|
||||||
data.data(), data.size(),
|
data.data(), data.size(),
|
||||||
/*last=*/true, [&](const char *compressed_data_chunk, size_t compressed_data_size) {
|
/*last=*/true,
|
||||||
compressed_data.insert(compressed_data.size(), compressed_data_chunk, compressed_data_size);
|
[&](const char *compressed_data_chunk, size_t compressed_data_size) {
|
||||||
|
compressed_data.insert(compressed_data.size(), compressed_data_chunk,
|
||||||
|
compressed_data_size);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
ASSERT_TRUE(result);
|
ASSERT_TRUE(result);
|
||||||
@ -3035,8 +3037,11 @@ TEST(GzipDecompressor, ChunkedDecompression) {
|
|||||||
std::min(compressed_data.size() - chunk_begin, chunk_size);
|
std::min(compressed_data.size() - chunk_begin, chunk_size);
|
||||||
bool result = decompressor.decompress(
|
bool result = decompressor.decompress(
|
||||||
compressed_data.data() + chunk_begin, current_chunk_size,
|
compressed_data.data() + chunk_begin, current_chunk_size,
|
||||||
[&](const char *decompressed_data_chunk, size_t decompressed_data_chunk_size) {
|
[&](const char *decompressed_data_chunk,
|
||||||
decompressed_data.insert(decompressed_data.size(), decompressed_data_chunk, decompressed_data_chunk_size);
|
size_t decompressed_data_chunk_size) {
|
||||||
|
decompressed_data.insert(decompressed_data.size(),
|
||||||
|
decompressed_data_chunk,
|
||||||
|
decompressed_data_chunk_size);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
ASSERT_TRUE(result);
|
ASSERT_TRUE(result);
|
||||||
@ -4974,5 +4979,48 @@ TEST(MultipartFormDataTest, LargeData) {
|
|||||||
svr.stop();
|
svr.stop();
|
||||||
t.join();
|
t.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(MultipartFormDataTest, WithPreamble) {
|
||||||
|
Server svr;
|
||||||
|
svr.Post("/post", [&](const Request &req, Response &res) {
|
||||||
|
res.set_content("ok", "text/plain");
|
||||||
|
});
|
||||||
|
|
||||||
|
thread t = thread([&] { svr.listen(HOST, PORT); });
|
||||||
|
while (!svr.is_running()) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string body =
|
||||||
|
"This is the preamble. It is to be ignored, though it\r\n"
|
||||||
|
"is a handy place for composition agents to include an\r\n"
|
||||||
|
"explanatory note to non-MIME conformant readers.\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"--simple boundary\r\n"
|
||||||
|
"Content-Disposition: form-data; name=\"field1\"\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"value1\r\n"
|
||||||
|
"--simple boundary\r\n"
|
||||||
|
"Content-Disposition: form-data; name=\"field2\"; "
|
||||||
|
"filename=\"example.txt\"\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"value2\r\n"
|
||||||
|
"--simple boundary--\r\n"
|
||||||
|
"This is the epilogue. It is also to be ignored.\r\n";
|
||||||
|
|
||||||
|
std::string content_type =
|
||||||
|
R"(multipart/form-data; boundary="simple boundary")";
|
||||||
|
|
||||||
|
Client cli(HOST, PORT);
|
||||||
|
auto res = cli.Post("/post", body, content_type.c_str());
|
||||||
|
|
||||||
|
ASSERT_TRUE(res);
|
||||||
|
EXPECT_EQ(200, res->status);
|
||||||
|
|
||||||
|
svr.stop();
|
||||||
|
t.join();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user