Skip to content

Commit fc2daf9

Browse files
Add server stream handler
Add complementary stream_handler callback to response. If set, it replaces all other content-serving mechanisms. No content-, or range-related headers are added. This provides a minimal interface to implement a WebSocket server.
1 parent 71ba7e7 commit fc2daf9

File tree

1 file changed

+45
-20
lines changed

1 file changed

+45
-20
lines changed

httplib.h

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,11 @@ using Progress = std::function<bool(uint64_t current, uint64_t total)>;
524524
struct Response;
525525
using ResponseHandler = std::function<bool(const Response &response)>;
526526

527+
class Stream;
528+
// Note: do not replace 'std::function<bool(Stream &strm)>' with StreamHandler;
529+
// signature is not final
530+
using StreamHandler = std::function<bool(Stream &strm)>;
531+
527532
struct MultipartFormData {
528533
std::string name;
529534
std::string content;
@@ -712,6 +717,9 @@ struct Response {
712717
const std::string &content_type);
713718
void set_file_content(const std::string &path);
714719

720+
// EXPERIMENTAL callback function signature may change
721+
void set_stream_handler(StreamHandler stream_handler);
722+
715723
Response() = default;
716724
Response(const Response &) = default;
717725
Response &operator=(const Response &) = default;
@@ -731,6 +739,8 @@ struct Response {
731739
bool content_provider_success_ = false;
732740
std::string file_content_path_;
733741
std::string file_content_content_type_;
742+
// EXPERIMENTAL function signature may change
743+
StreamHandler stream_handler_;
734744
};
735745

736746
class Stream {
@@ -5906,6 +5916,10 @@ inline void Response::set_file_content(const std::string &path) {
59065916
file_content_path_ = path;
59075917
}
59085918

5919+
inline void Response::set_stream_handler(StreamHandler stream_handler) {
5920+
stream_handler_ = std::move(stream_handler);
5921+
}
5922+
59095923
// Result implementation
59105924
inline bool Result::has_request_header(const std::string &key) const {
59115925
return request_headers_.find(key) != request_headers_.end();
@@ -6548,18 +6562,21 @@ inline bool Server::write_response_core(Stream &strm, bool close_connection,
65486562
res.set_header("Keep-Alive", s);
65496563
}
65506564

6551-
if ((!res.body.empty() || res.content_length_ > 0 || res.content_provider_) &&
6552-
!res.has_header("Content-Type")) {
6553-
res.set_header("Content-Type", "text/plain");
6554-
}
6565+
if (!res.stream_handler_) {
6566+
if ((!res.body.empty() || res.content_length_ > 0 ||
6567+
res.content_provider_) &&
6568+
!res.has_header("Content-Type")) {
6569+
res.set_header("Content-Type", "text/plain");
6570+
}
65556571

6556-
if (res.body.empty() && !res.content_length_ && !res.content_provider_ &&
6557-
!res.has_header("Content-Length")) {
6558-
res.set_header("Content-Length", "0");
6559-
}
6572+
if (res.body.empty() && !res.content_length_ && !res.content_provider_ &&
6573+
!res.has_header("Content-Length")) {
6574+
res.set_header("Content-Length", "0");
6575+
}
65606576

6561-
if (req.method == "HEAD" && !res.has_header("Accept-Ranges")) {
6562-
res.set_header("Accept-Ranges", "bytes");
6577+
if (req.method == "HEAD" && !res.has_header("Accept-Ranges")) {
6578+
res.set_header("Accept-Ranges", "bytes");
6579+
}
65636580
}
65646581

65656582
if (post_routing_handler_) { post_routing_handler_(req, res); }
@@ -6577,16 +6594,24 @@ inline bool Server::write_response_core(Stream &strm, bool close_connection,
65776594

65786595
// Body
65796596
auto ret = true;
6580-
if (req.method != "HEAD") {
6581-
if (!res.body.empty()) {
6582-
if (!detail::write_data(strm, res.body.data(), res.body.size())) {
6583-
ret = false;
6584-
}
6585-
} else if (res.content_provider_) {
6586-
if (write_content_with_provider(strm, req, res, boundary, content_type)) {
6587-
res.content_provider_success_ = true;
6588-
} else {
6589-
ret = false;
6597+
if (res.stream_handler_) {
6598+
// Log early
6599+
if (logger_) { logger_(req, res); }
6600+
6601+
return res.stream_handler_(strm);
6602+
} else {
6603+
if (req.method != "HEAD") {
6604+
if (!res.body.empty()) {
6605+
if (!detail::write_data(strm, res.body.data(), res.body.size())) {
6606+
ret = false;
6607+
}
6608+
} else if (res.content_provider_) {
6609+
if (write_content_with_provider(strm, req, res, boundary,
6610+
content_type)) {
6611+
res.content_provider_success_ = true;
6612+
} else {
6613+
ret = false;
6614+
}
65906615
}
65916616
}
65926617
}

0 commit comments

Comments
 (0)