Skip to content

Commit e89bfd2

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 a4b2c61 commit e89bfd2

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
@@ -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;
@@ -725,6 +730,9 @@ struct Response {
725730
const std::string &content_type);
726731
void set_file_content(const std::string &path);
727732

733+
// EXPERIMENTAL callback function signature may change
734+
void set_stream_handler(StreamHandler stream_handler);
735+
728736
Response() = default;
729737
Response(const Response &) = default;
730738
Response &operator=(const Response &) = default;
@@ -744,6 +752,8 @@ struct Response {
744752
bool content_provider_success_ = false;
745753
std::string file_content_path_;
746754
std::string file_content_content_type_;
755+
// EXPERIMENTAL function signature may change
756+
StreamHandler stream_handler_;
747757
};
748758

749759
class Stream {
@@ -5972,6 +5982,10 @@ inline void Response::set_file_content(const std::string &path) {
59725982
file_content_path_ = path;
59735983
}
59745984

5985+
inline void Response::set_stream_handler(StreamHandler stream_handler) {
5986+
stream_handler_ = std::move(stream_handler);
5987+
}
5988+
59755989
// Result implementation
59765990
inline bool Result::has_request_header(const std::string &key) const {
59775991
return request_headers_.find(key) != request_headers_.end();
@@ -6608,18 +6622,21 @@ inline bool Server::write_response_core(Stream &strm, bool close_connection,
66086622
res.set_header("Keep-Alive", s);
66096623
}
66106624

6611-
if ((!res.body.empty() || res.content_length_ > 0 || res.content_provider_) &&
6612-
!res.has_header("Content-Type")) {
6613-
res.set_header("Content-Type", "text/plain");
6614-
}
6625+
if (!res.stream_handler_) {
6626+
if ((!res.body.empty() || res.content_length_ > 0 ||
6627+
res.content_provider_) &&
6628+
!res.has_header("Content-Type")) {
6629+
res.set_header("Content-Type", "text/plain");
6630+
}
66156631

6616-
if (res.body.empty() && !res.content_length_ && !res.content_provider_ &&
6617-
!res.has_header("Content-Length")) {
6618-
res.set_header("Content-Length", "0");
6619-
}
6632+
if (res.body.empty() && !res.content_length_ && !res.content_provider_ &&
6633+
!res.has_header("Content-Length")) {
6634+
res.set_header("Content-Length", "0");
6635+
}
66206636

6621-
if (req.method == "HEAD" && !res.has_header("Accept-Ranges")) {
6622-
res.set_header("Accept-Ranges", "bytes");
6637+
if (req.method == "HEAD" && !res.has_header("Accept-Ranges")) {
6638+
res.set_header("Accept-Ranges", "bytes");
6639+
}
66236640
}
66246641

66256642
if (post_routing_handler_) { post_routing_handler_(req, res); }
@@ -6637,16 +6654,24 @@ inline bool Server::write_response_core(Stream &strm, bool close_connection,
66376654

66386655
// Body
66396656
auto ret = true;
6640-
if (req.method != "HEAD") {
6641-
if (!res.body.empty()) {
6642-
if (!detail::write_data(strm, res.body.data(), res.body.size())) {
6643-
ret = false;
6644-
}
6645-
} else if (res.content_provider_) {
6646-
if (write_content_with_provider(strm, req, res, boundary, content_type)) {
6647-
res.content_provider_success_ = true;
6648-
} else {
6649-
ret = false;
6657+
if (res.stream_handler_) {
6658+
// Log early
6659+
if (logger_) { logger_(req, res); }
6660+
6661+
return res.stream_handler_(strm);
6662+
} else {
6663+
if (req.method != "HEAD") {
6664+
if (!res.body.empty()) {
6665+
if (!detail::write_data(strm, res.body.data(), res.body.size())) {
6666+
ret = false;
6667+
}
6668+
} else if (res.content_provider_) {
6669+
if (write_content_with_provider(strm, req, res, boundary,
6670+
content_type)) {
6671+
res.content_provider_success_ = true;
6672+
} else {
6673+
ret = false;
6674+
}
66506675
}
66516676
}
66526677
}

0 commit comments

Comments
 (0)