Skip to content

Commit 5a43bb8

Browse files
committed
Implemented yhirose#946 in a different way
1 parent 0104614 commit 5a43bb8

File tree

3 files changed

+55
-7
lines changed

3 files changed

+55
-7
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ svr.Get("/stream", [&](const Request &req, Response &res) {
266266
sink.write(&d[offset], std::min(length, DATA_CHUNK_SIZE));
267267
return true; // return 'false' if you want to cancel the process.
268268
},
269-
[data] { delete data; });
269+
[data](bool success) { delete data; });
270270
});
271271
```
272272

httplib.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ using ContentProvider =
337337
using ContentProviderWithoutLength =
338338
std::function<bool(size_t offset, DataSink &sink)>;
339339

340-
using ContentProviderResourceReleaser = std::function<void()>;
340+
using ContentProviderResourceReleaser = std::function<void(bool success)>;
341341

342342
using ContentReceiverWithProgress =
343343
std::function<bool(const char *data, size_t data_length, uint64_t offset,
@@ -465,7 +465,7 @@ struct Response {
465465
Response &operator=(Response &&) = default;
466466
~Response() {
467467
if (content_provider_resource_releaser_) {
468-
content_provider_resource_releaser_();
468+
content_provider_resource_releaser_(content_provider_success_);
469469
}
470470
}
471471

@@ -474,6 +474,7 @@ struct Response {
474474
ContentProvider content_provider_;
475475
ContentProviderResourceReleaser content_provider_resource_releaser_;
476476
bool is_chunked_content_provider_ = false;
477+
bool content_provider_success_ = false;
477478
};
478479

479480
class Stream {
@@ -4614,8 +4615,11 @@ inline bool Server::write_response_core(Stream &strm, bool close_connection,
46144615
if (!res.body.empty()) {
46154616
if (!strm.write(res.body)) { ret = false; }
46164617
} else if (res.content_provider_) {
4617-
if (!write_content_with_provider(strm, req, res, boundary,
4618-
content_type)) {
4618+
if (write_content_with_provider(strm, req, res, boundary,
4619+
content_type)) {
4620+
res.content_provider_success_ = true;
4621+
} else {
4622+
res.content_provider_success_ = false;
46194623
ret = false;
46204624
}
46214625
}

test/test.cc

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,7 +1378,10 @@ class ServerTest : public ::testing::Test {
13781378
(*i)++;
13791379
return true;
13801380
},
1381-
[i] { delete i; });
1381+
[i](bool success) {
1382+
EXPECT_TRUE(success);
1383+
delete i;
1384+
});
13821385
})
13831386
.Get("/streamed",
13841387
[&](const Request & /*req*/, Response &res) {
@@ -1405,7 +1408,10 @@ class ServerTest : public ::testing::Test {
14051408
EXPECT_TRUE(ret);
14061409
return true;
14071410
},
1408-
[data] { delete data; });
1411+
[data](bool success) {
1412+
EXPECT_TRUE(success);
1413+
delete data;
1414+
});
14091415
})
14101416
.Get("/streamed-cancel",
14111417
[&](const Request & /*req*/, Response &res) {
@@ -3567,6 +3573,44 @@ TEST(KeepAliveTest, ReadTimeout) {
35673573
ASSERT_FALSE(svr.is_running());
35683574
}
35693575

3576+
TEST(ClientProblemDetectionTest, ContentProvider) {
3577+
Server svr;
3578+
3579+
size_t content_length = 1024 * 1024;
3580+
3581+
svr.Get("/hi", [&](const Request & /*req*/, Response &res) {
3582+
res.set_content_provider(
3583+
content_length, "text/plain",
3584+
[&](size_t offset, size_t length, DataSink &sink) {
3585+
auto out_len = std::min(length, static_cast<size_t>(1024));
3586+
std::string out(out_len, '@');
3587+
sink.write(out.data(), out_len);
3588+
return offset < 4096;
3589+
},
3590+
[](bool success) { ASSERT_FALSE(success); });
3591+
});
3592+
3593+
auto listen_thread = std::thread([&svr]() { svr.listen("localhost", PORT); });
3594+
while (!svr.is_running()) {
3595+
std::this_thread::sleep_for(std::chrono::milliseconds(1));
3596+
}
3597+
3598+
// Give GET time to get a few messages.
3599+
std::this_thread::sleep_for(std::chrono::seconds(1));
3600+
3601+
Client cli("localhost", PORT);
3602+
3603+
auto res = cli.Get("/hi", [&](const char * /*data*/, size_t /*data_length*/) {
3604+
return false;
3605+
});
3606+
3607+
ASSERT_FALSE(res);
3608+
3609+
svr.stop();
3610+
listen_thread.join();
3611+
ASSERT_FALSE(svr.is_running());
3612+
}
3613+
35703614
TEST(ErrorHandlerWithContentProviderTest, ErrorHandler) {
35713615
Server svr;
35723616

0 commit comments

Comments
 (0)