Skip to content

Commit 327d625

Browse files
Add client stream handler
Introduce a new request callback, stream_handler. If set, it replaces all other content-serving mechanisms. The handler is not called in response to HEAD or CONNECT requests, or when following a redirect. Content-related default header fields are not added to the request. In conjunction with a response handler, it provides a minimal interface to implement a WebSocket client.
1 parent a4b2c61 commit 327d625

File tree

1 file changed

+30
-7
lines changed

1 file changed

+30
-7
lines changed

httplib.h

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,11 @@ using Progress = std::function<bool(uint64_t current, uint64_t total)>;
537537
struct Response;
538538
using ResponseHandler = std::function<bool(const Response &response)>;
539539

540+
class Stream;
541+
// Note: do not replace 'std::function<bool(Stream &strm)>' with StreamHandler;
542+
// signature is not final
543+
using StreamHandler = std::function<bool(Stream &strm)>;
544+
540545
struct MultipartFormData {
541546
std::string name;
542547
std::string content;
@@ -654,6 +659,7 @@ struct Request {
654659

655660
// for client
656661
ResponseHandler response_handler;
662+
StreamHandler stream_handler; // EXPERIMENTAL function signature may change
657663
ContentReceiverWithProgress content_receiver;
658664
Progress progress;
659665
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
@@ -1182,6 +1188,7 @@ enum class Error {
11821188
Compression,
11831189
ConnectionTimeout,
11841190
ProxyConnection,
1191+
StreamHandler,
11851192

11861193
// For internal use only
11871194
SSLPeerCouldBeClosed_,
@@ -2272,6 +2279,7 @@ inline std::string to_string(const Error error) {
22722279
case Error::Compression: return "Compression failed";
22732280
case Error::ConnectionTimeout: return "Connection timed out";
22742281
case Error::ProxyConnection: return "Proxy connection failed";
2282+
case Error::StreamHandler: return "Stream handler failed";
22752283
case Error::Unknown: return "Unknown";
22762284
default: break;
22772285
}
@@ -7864,10 +7872,12 @@ inline bool ClientImpl::write_request(Stream &strm, Request &req,
78647872
}
78657873
}
78667874

7867-
if (!req.has_header("Accept")) { req.set_header("Accept", "*/*"); }
7875+
if (!req.stream_handler && !req.has_header("Accept")) {
7876+
req.set_header("Accept", "*/*");
7877+
}
78687878

78697879
if (!req.content_receiver) {
7870-
if (!req.has_header("Accept-Encoding")) {
7880+
if (!req.stream_handler && !req.has_header("Accept-Encoding")) {
78717881
std::string accept_encoding;
78727882
#ifdef CPPHTTPLIB_BROTLI_SUPPORT
78737883
accept_encoding = "br";
@@ -7885,7 +7895,7 @@ inline bool ClientImpl::write_request(Stream &strm, Request &req,
78857895
req.set_header("User-Agent", agent);
78867896
}
78877897
#endif
7888-
};
7898+
}
78897899

78907900
if (req.body.empty()) {
78917901
if (req.content_provider_) {
@@ -8117,10 +8127,23 @@ inline bool ClientImpl::process_request(Stream &strm, Request &req,
81178127
res.status != StatusCode::NotModified_304 &&
81188128
follow_location_;
81198129

8120-
if (req.response_handler && !redirect) {
8121-
if (!req.response_handler(res)) {
8122-
error = Error::Canceled;
8123-
return false;
8130+
if (!redirect) {
8131+
if (req.response_handler) {
8132+
if (!req.response_handler(res)) {
8133+
error = Error::Canceled;
8134+
return false;
8135+
}
8136+
}
8137+
8138+
if (req.stream_handler) {
8139+
// Log early
8140+
if (logger_) { logger_(req, res); }
8141+
8142+
if (!req.stream_handler(strm)) {
8143+
error = Error::StreamHandler;
8144+
return false;
8145+
}
8146+
return true;
81248147
}
81258148
}
81268149

0 commit comments

Comments
 (0)