diff --git a/httplib.h b/httplib.h index 84c8c16d92..47b0b76a0f 100644 --- a/httplib.h +++ b/httplib.h @@ -4105,16 +4105,21 @@ inline bool Client::write_request(Stream &strm, const Request &req, if (req.content_provider) { size_t offset = 0; size_t end_offset = req.content_length; + ssize_t written_length = 0; DataSink data_sink; data_sink.write = [&](const char *d, size_t l) { - auto written_length = strm.write(d, l); + written_length = strm.write(d, l); offset += static_cast(written_length); }; - data_sink.is_writable = [&](void) { return strm.is_writable(); }; + data_sink.is_writable = [&](void) { + return strm.is_writable() && written_length >= 0; + }; + data_sink.done = [&](void) { written_length = -1; }; while (offset < end_offset) { req.content_provider(offset, end_offset - offset, data_sink); + if (written_length < 0) { return false; } } } } else { @@ -4139,6 +4144,7 @@ inline std::shared_ptr Client::send_with_content_provider( if (compress_) { if (content_provider) { size_t offset = 0; + ssize_t written_length = 0; DataSink data_sink; data_sink.write = [&](const char *data, size_t data_len) { @@ -4146,9 +4152,11 @@ inline std::shared_ptr Client::send_with_content_provider( offset += data_len; }; data_sink.is_writable = [&](void) { return true; }; + data_sink.done = [&](void) { written_length = -1; }; while (offset < content_length) { content_provider(offset, content_length - offset, data_sink); + if (written_length < 0) { return nullptr; } } } else { req.body = body; diff --git a/test/test.cc b/test/test.cc index f5ad332b7c..c4a23e5ee2 100644 --- a/test/test.cc +++ b/test/test.cc @@ -1928,6 +1928,17 @@ TEST_F(ServerTest, PutWithContentProvider) { EXPECT_EQ("PUT", res->body); } +TEST_F(ServerTest, PostWithContentProviderAbort) { + auto res = cli_.Post( + "/post", 42, + [](size_t /*offset*/, size_t /*length*/, httplib::DataSink &sink) { + sink.done(); + }, + "text/plain"); + + ASSERT_TRUE(res == nullptr); +} + #ifdef CPPHTTPLIB_ZLIB_SUPPORT TEST_F(ServerTest, PutWithContentProviderWithGzip) { cli_.set_compress(true);