Skip to content

Commit ca5a50d

Browse files
committed
Fix #349
1 parent b251668 commit ca5a50d

File tree

2 files changed

+49
-3
lines changed

2 files changed

+49
-3
lines changed

README.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ svr.set_logger([](const auto& req, const auto& res) {
106106
});
107107
```
108108

109-
### Error Handler
109+
### Error handler
110110

111111
```cpp
112112
svr.set_error_handler([](const auto& req, auto& res) {
@@ -232,6 +232,24 @@ svr.new_task_queue = [] {
232232
};
233233
```
234234

235+
### 'Expect: 100-continue' handler
236+
237+
As default, the server sends `100 Continue` response for `Expect: 100-continue` header.
238+
239+
```cpp
240+
// Send a '417 Expectation Failed' response.
241+
svr.set_expect_100_continue_handler([](const Request &req, Response &res) {
242+
return 417;
243+
});
244+
```
245+
246+
```cpp
247+
// Send a final status without reading the message body.
248+
svr.set_expect_100_continue_handler([](const Request &req, Response &res) {
249+
return res.status = 401;
250+
});
251+
```
252+
235253
Client Example
236254
--------------
237255

httplib.h

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,8 @@ class Server {
448448
using Handler = std::function<void(const Request &, Response &)>;
449449
using HandlerWithContentReader = std::function<void(
450450
const Request &, Response &, const ContentReader &content_reader)>;
451+
using Expect100ContinueHandler =
452+
std::function<int(const Request &, Response &)>;
451453

452454
Server();
453455

@@ -476,6 +478,8 @@ class Server {
476478
void set_error_handler(Handler handler);
477479
void set_logger(Logger logger);
478480

481+
void set_expect_100_continue_handler(Expect100ContinueHandler handler);
482+
479483
void set_keep_alive_max_count(size_t count);
480484
void set_read_timeout(time_t sec, time_t usec);
481485
void set_payload_max_length(size_t length);
@@ -553,6 +557,7 @@ class Server {
553557
Handlers options_handlers_;
554558
Handler error_handler_;
555559
Logger logger_;
560+
Expect100ContinueHandler expect_100_continue_handler_;
556561
};
557562

558563
class Client {
@@ -1594,6 +1599,7 @@ find_content_type(const std::string &path,
15941599

15951600
inline const char *status_message(int status) {
15961601
switch (status) {
1602+
case 100: return "Continue";
15971603
case 200: return "OK";
15981604
case 202: return "Accepted";
15991605
case 204: return "No Content";
@@ -1610,6 +1616,7 @@ inline const char *status_message(int status) {
16101616
case 414: return "Request-URI Too Long";
16111617
case 415: return "Unsupported Media Type";
16121618
case 416: return "Range Not Satisfiable";
1619+
case 417: return "Expectation Failed";
16131620
case 503: return "Service Unavailable";
16141621

16151622
default:
@@ -2931,6 +2938,11 @@ inline void Server::set_error_handler(Handler handler) {
29312938

29322939
inline void Server::set_logger(Logger logger) { logger_ = std::move(logger); }
29332940

2941+
inline void
2942+
Server::set_expect_100_continue_handler(Expect100ContinueHandler handler) {
2943+
expect_100_continue_handler_ = std::move(handler);
2944+
}
2945+
29342946
inline void Server::set_keep_alive_max_count(size_t count) {
29352947
keep_alive_max_count_ = count;
29362948
}
@@ -3012,11 +3024,12 @@ inline bool Server::write_response(Stream &strm, bool last_connection,
30123024
res.set_header("Connection", "Keep-Alive");
30133025
}
30143026

3015-
if (!res.has_header("Content-Type")) {
3027+
if (!res.has_header("Content-Type") &&
3028+
(!res.body.empty() || res.content_length > 0)) {
30163029
res.set_header("Content-Type", "text/plain");
30173030
}
30183031

3019-
if (!res.has_header("Accept-Ranges")) {
3032+
if (!res.has_header("Accept-Ranges") && req.method == "HEAD") {
30203033
res.set_header("Accept-Ranges", "bytes");
30213034
}
30223035

@@ -3491,6 +3504,21 @@ Server::process_request(Stream &strm, bool last_connection,
34913504

34923505
if (setup_request) { setup_request(req); }
34933506

3507+
if (req.get_header_value("Expect") == "100-continue") {
3508+
auto status = 100;
3509+
if (expect_100_continue_handler_) {
3510+
status = expect_100_continue_handler_(req, res);
3511+
}
3512+
switch (status) {
3513+
case 100:
3514+
case 417:
3515+
strm.write_format("HTTP/1.1 %d %s\r\n\r\n", status,
3516+
detail::status_message(status));
3517+
break;
3518+
default: return write_response(strm, last_connection, req, res);
3519+
}
3520+
}
3521+
34943522
// Rounting
34953523
if (routing(req, res, strm, last_connection)) {
34963524
if (res.status == -1) { res.status = req.ranges.empty() ? 200 : 206; }

0 commit comments

Comments
 (0)