@@ -227,7 +227,10 @@ class DataSink {
227227};
228228
229229using ContentProvider =
230- std::function<void (size_t offset, size_t length, DataSink &sink)>;
230+ std::function<bool (size_t offset, size_t length, DataSink &sink)>;
231+
232+ using ChunkedContentProvider =
233+ std::function<bool (size_t offset, DataSink &sink)>;
231234
232235using ContentReceiver =
233236 std::function<bool (const char *data, size_t data_length)>;
@@ -323,13 +326,11 @@ struct Response {
323326 void set_content (std::string s, const char *content_type);
324327
325328 void set_content_provider (
326- size_t length,
327- std::function<void (size_t offset, size_t length, DataSink &sink)>
328- provider,
329+ size_t length, ContentProvider provider,
329330 std::function<void ()> resource_releaser = [] {});
330331
331332 void set_chunked_content_provider (
332- std::function< void ( size_t offset, DataSink &sink)> provider,
333+ ChunkedContentProvider provider,
333334 std::function<void ()> resource_releaser = [] {});
334335
335336 Response () = default ;
@@ -2074,22 +2075,25 @@ inline ssize_t write_content(Stream &strm, ContentProvider content_provider,
20742075 size_t offset, size_t length) {
20752076 size_t begin_offset = offset;
20762077 size_t end_offset = offset + length;
2077- while (offset < end_offset) {
2078- ssize_t written_length = 0 ;
20792078
2080- DataSink data_sink;
2081- data_sink.write = [&](const char *d, size_t l) {
2082- offset += l;
2083- written_length = strm.write (d, l);
2084- };
2085- data_sink.done = [&](void ) { written_length = -1 ; };
2086- data_sink.is_writable = [&](void ) {
2087- return strm.is_writable () && written_length >= 0 ;
2088- };
2079+ ssize_t written_length = 0 ;
2080+
2081+ DataSink data_sink;
2082+ data_sink.write = [&](const char *d, size_t l) {
2083+ offset += l;
2084+ written_length = strm.write (d, l);
2085+ };
2086+ data_sink.is_writable = [&](void ) {
2087+ return strm.is_writable () && written_length >= 0 ;
2088+ };
20892089
2090- content_provider (offset, end_offset - offset, data_sink);
2090+ while (offset < end_offset) {
2091+ if (!content_provider (offset, end_offset - offset, data_sink)) {
2092+ return -1 ;
2093+ }
20912094 if (written_length < 0 ) { return written_length; }
20922095 }
2096+
20932097 return static_cast <ssize_t >(offset - begin_offset);
20942098}
20952099
@@ -2100,31 +2104,32 @@ inline ssize_t write_content_chunked(Stream &strm,
21002104 size_t offset = 0 ;
21012105 auto data_available = true ;
21022106 ssize_t total_written_length = 0 ;
2103- while (data_available && !is_shutting_down ()) {
2104- ssize_t written_length = 0 ;
21052107
2106- DataSink data_sink;
2107- data_sink.write = [&](const char *d, size_t l) {
2108- data_available = l > 0 ;
2109- offset += l;
2108+ ssize_t written_length = 0 ;
21102109
2111- // Emit chunked response header and footer for each chunk
2112- auto chunk = from_i_to_hex (l) + " \r\n " + std::string (d, l) + " \r\n " ;
2113- written_length = strm.write (chunk);
2114- };
2115- data_sink.done = [&](void ) {
2116- data_available = false ;
2117- written_length = strm.write (" 0\r\n\r\n " );
2118- };
2119- data_sink.is_writable = [&](void ) {
2120- return strm.is_writable () && written_length >= 0 ;
2121- };
2110+ DataSink data_sink;
2111+ data_sink.write = [&](const char *d, size_t l) {
2112+ data_available = l > 0 ;
2113+ offset += l;
21222114
2123- content_provider (offset, 0 , data_sink);
2115+ // Emit chunked response header and footer for each chunk
2116+ auto chunk = from_i_to_hex (l) + " \r\n " + std::string (d, l) + " \r\n " ;
2117+ written_length = strm.write (chunk);
2118+ };
2119+ data_sink.done = [&](void ) {
2120+ data_available = false ;
2121+ written_length = strm.write (" 0\r\n\r\n " );
2122+ };
2123+ data_sink.is_writable = [&](void ) {
2124+ return strm.is_writable () && written_length >= 0 ;
2125+ };
21242126
2127+ while (data_available && !is_shutting_down ()) {
2128+ if (!content_provider (offset, 0 , data_sink)) { return -1 ; }
21252129 if (written_length < 0 ) { return written_length; }
21262130 total_written_length += written_length;
21272131 }
2132+
21282133 return total_written_length;
21292134}
21302135
@@ -2904,24 +2909,23 @@ inline void Response::set_content(std::string s, const char *content_type) {
29042909 set_header (" Content-Type" , content_type);
29052910}
29062911
2907- inline void Response::set_content_provider (
2908- size_t in_length,
2909- std::function<void (size_t offset, size_t length, DataSink &sink)> provider,
2910- std::function<void()> resource_releaser) {
2912+ inline void
2913+ Response::set_content_provider (size_t in_length, ContentProvider provider,
2914+ std::function<void ()> resource_releaser) {
29112915 assert (in_length > 0 );
29122916 content_length = in_length;
29132917 content_provider = [provider](size_t offset, size_t length, DataSink &sink) {
2914- provider (offset, length, sink);
2918+ return provider (offset, length, sink);
29152919 };
29162920 content_provider_resource_releaser = resource_releaser;
29172921}
29182922
29192923inline void Response::set_chunked_content_provider (
2920- std::function< void ( size_t offset, DataSink &sink)> provider,
2924+ ChunkedContentProvider provider,
29212925 std::function<void ()> resource_releaser) {
29222926 content_length = 0 ;
29232927 content_provider = [provider](size_t offset, size_t , DataSink &sink) {
2924- provider (offset, sink);
2928+ return provider (offset, sink);
29252929 };
29262930 content_provider_resource_releaser = resource_releaser;
29272931}
@@ -4106,15 +4110,22 @@ inline bool Client::write_request(Stream &strm, const Request &req,
41064110 size_t offset = 0 ;
41074111 size_t end_offset = req.content_length ;
41084112
4113+ ssize_t written_length = 0 ;
4114+
41094115 DataSink data_sink;
41104116 data_sink.write = [&](const char *d, size_t l) {
4111- auto written_length = strm.write (d, l);
4117+ written_length = strm.write (d, l);
41124118 offset += static_cast <size_t >(written_length);
41134119 };
4114- data_sink.is_writable = [&](void ) { return strm.is_writable (); };
4120+ data_sink.is_writable = [&](void ) {
4121+ return strm.is_writable () && written_length >= 0 ;
4122+ };
41154123
41164124 while (offset < end_offset) {
4117- req.content_provider (offset, end_offset - offset, data_sink);
4125+ if (!req.content_provider (offset, end_offset - offset, data_sink)) {
4126+ return false ;
4127+ }
4128+ if (written_length < 0 ) { return false ; }
41184129 }
41194130 }
41204131 } else {
@@ -4148,7 +4159,9 @@ inline std::shared_ptr<Response> Client::send_with_content_provider(
41484159 data_sink.is_writable = [&](void ) { return true ; };
41494160
41504161 while (offset < content_length) {
4151- content_provider (offset, content_length - offset, data_sink);
4162+ if (!content_provider (offset, content_length - offset, data_sink)) {
4163+ return nullptr ;
4164+ }
41524165 }
41534166 } else {
41544167 req.body = body;
0 commit comments