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.
This commit is contained in:
parent
fc2daf930c
commit
b18a6e8456
32
httplib.h
32
httplib.h
@ -646,6 +646,7 @@ struct Request {
|
|||||||
|
|
||||||
// for client
|
// for client
|
||||||
ResponseHandler response_handler;
|
ResponseHandler response_handler;
|
||||||
|
StreamHandler stream_handler; // EXPERIMENTAL function signature may change
|
||||||
ContentReceiverWithProgress content_receiver;
|
ContentReceiverWithProgress content_receiver;
|
||||||
Progress progress;
|
Progress progress;
|
||||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||||
@ -1180,6 +1181,7 @@ enum class Error {
|
|||||||
Compression,
|
Compression,
|
||||||
ConnectionTimeout,
|
ConnectionTimeout,
|
||||||
ProxyConnection,
|
ProxyConnection,
|
||||||
|
StreamHandler,
|
||||||
|
|
||||||
// For internal use only
|
// For internal use only
|
||||||
SSLPeerCouldBeClosed_,
|
SSLPeerCouldBeClosed_,
|
||||||
@ -2270,6 +2272,7 @@ inline std::string to_string(const Error error) {
|
|||||||
case Error::Compression: return "Compression failed";
|
case Error::Compression: return "Compression failed";
|
||||||
case Error::ConnectionTimeout: return "Connection timed out";
|
case Error::ConnectionTimeout: return "Connection timed out";
|
||||||
case Error::ProxyConnection: return "Proxy connection failed";
|
case Error::ProxyConnection: return "Proxy connection failed";
|
||||||
|
case Error::StreamHandler: return "Stream handler failed";
|
||||||
case Error::Unknown: return "Unknown";
|
case Error::Unknown: return "Unknown";
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
@ -7825,10 +7828,12 @@ inline bool ClientImpl::write_request(Stream &strm, Request &req,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!req.has_header("Accept")) { req.set_header("Accept", "*/*"); }
|
if (!req.stream_handler && !req.has_header("Accept")) {
|
||||||
|
req.set_header("Accept", "*/*");
|
||||||
|
}
|
||||||
|
|
||||||
if (!req.content_receiver) {
|
if (!req.content_receiver) {
|
||||||
if (!req.has_header("Accept-Encoding")) {
|
if (!req.stream_handler && !req.has_header("Accept-Encoding")) {
|
||||||
std::string accept_encoding;
|
std::string accept_encoding;
|
||||||
#ifdef CPPHTTPLIB_BROTLI_SUPPORT
|
#ifdef CPPHTTPLIB_BROTLI_SUPPORT
|
||||||
accept_encoding = "br";
|
accept_encoding = "br";
|
||||||
@ -7846,7 +7851,7 @@ inline bool ClientImpl::write_request(Stream &strm, Request &req,
|
|||||||
req.set_header("User-Agent", agent);
|
req.set_header("User-Agent", agent);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
};
|
}
|
||||||
|
|
||||||
if (req.body.empty()) {
|
if (req.body.empty()) {
|
||||||
if (req.content_provider_) {
|
if (req.content_provider_) {
|
||||||
@ -8078,10 +8083,23 @@ inline bool ClientImpl::process_request(Stream &strm, Request &req,
|
|||||||
res.status != StatusCode::NotModified_304 &&
|
res.status != StatusCode::NotModified_304 &&
|
||||||
follow_location_;
|
follow_location_;
|
||||||
|
|
||||||
if (req.response_handler && !redirect) {
|
if (!redirect) {
|
||||||
if (!req.response_handler(res)) {
|
if (req.response_handler) {
|
||||||
error = Error::Canceled;
|
if (!req.response_handler(res)) {
|
||||||
return false;
|
error = Error::Canceled;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.stream_handler) {
|
||||||
|
// Log early
|
||||||
|
if (logger_) { logger_(req, res); }
|
||||||
|
|
||||||
|
if (!req.stream_handler(strm)) {
|
||||||
|
error = Error::StreamHandler;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user