|
5 | 5 | // MIT License
|
6 | 6 | //
|
7 | 7 |
|
8 |
| -#include <cstdio> |
9 |
| -#include <httplib.h> |
| 8 | +#include <chrono> |
| 9 | +#include <ctime> |
| 10 | +#include <format> |
| 11 | +#include <iomanip> |
10 | 12 | #include <iostream>
|
| 13 | +#include <sstream> |
11 | 14 |
|
12 |
| -using namespace httplib; |
13 |
| -using namespace std; |
| 15 | +#include <httplib.h> |
14 | 16 |
|
15 |
| -auto error_html = R"(<html> |
16 |
| -<head><title>%d %s</title></head> |
| 17 | +constexpr auto error_html = R"(<html> |
| 18 | +<head><title>{} {}</title></head> |
17 | 19 | <body>
|
18 | 20 | <center><h1>404 Not Found</h1></center>
|
19 |
| -<hr><center>cpp-httplib/%s</center> |
| 21 | +<hr><center>cpp-httplib/{}</center> |
20 | 22 | </body>
|
21 | 23 | </html>
|
22 | 24 | )";
|
23 | 25 |
|
| 26 | +std::string time_local() { |
| 27 | + auto p = std::chrono::system_clock::now(); |
| 28 | + auto t = std::chrono::system_clock::to_time_t(p); |
| 29 | + |
| 30 | + std::stringstream ss; |
| 31 | + ss << std::put_time(std::localtime(&t), "%d/%b/%Y:%H:%M:%S %z"); |
| 32 | + return ss.str(); |
| 33 | +} |
| 34 | + |
| 35 | +std::string log(auto &req, auto &res) { |
| 36 | + auto remote_user = "-"; // TODO: |
| 37 | + auto request = std::format("{} {} {}", req.method, req.path, req.version); |
| 38 | + auto body_bytes_sent = res.get_header_value("Content-Length"); |
| 39 | + auto http_referer = "-"; // TODO: |
| 40 | + auto http_user_agent = req.get_header_value("User-Agent", "-"); |
| 41 | + |
| 42 | + // NOTE: From NGINX defualt access log format |
| 43 | + // log_format combined '$remote_addr - $remote_user [$time_local] ' |
| 44 | + // '"$request" $status $body_bytes_sent ' |
| 45 | + // '"$http_referer" "$http_user_agent"'; |
| 46 | + return std::format(R"({} - {} [{}] "{}" {} {} "{}" "{}")", req.remote_addr, |
| 47 | + remote_user, time_local(), request, res.status, |
| 48 | + body_bytes_sent, http_referer, http_user_agent); |
| 49 | +} |
| 50 | + |
24 | 51 | int main(int argc, const char **argv) {
|
25 |
| - Server svr; |
| 52 | + auto base_dir = "./html"; |
| 53 | + auto host = "0.0.0.0"; |
| 54 | + auto port = 80; |
| 55 | + |
| 56 | + httplib::Server svr; |
26 | 57 |
|
27 |
| - svr.set_error_handler([](const Request & /*req*/, Response &res) { |
28 |
| - char buf[BUFSIZ]; |
29 |
| - snprintf(buf, sizeof(buf), error_html, res.status, |
30 |
| - status_message(res.status), CPPHTTPLIB_VERSION); |
31 |
| - res.set_content(buf, "text/html"); |
| 58 | + svr.set_error_handler([](auto & /*req*/, auto &res) { |
| 59 | + auto body = |
| 60 | + std::format(error_html, res.status, httplib::status_message(res.status), |
| 61 | + CPPHTTPLIB_VERSION); |
| 62 | + |
| 63 | + res.set_content(body, "text/html"); |
32 | 64 | });
|
33 | 65 |
|
34 |
| - svr.set_mount_point("/", "./html"); |
| 66 | + svr.set_logger( |
| 67 | + [](auto &req, auto &res) { std::cout << log(req, res) << std::endl; }); |
| 68 | + |
| 69 | + svr.set_mount_point("/", base_dir); |
| 70 | + |
| 71 | + std::cout << std::format("Serving HTTP on {0} port {1} ...", host, port) |
| 72 | + << std::endl; |
35 | 73 |
|
36 |
| - svr.listen("0.0.0.0", 80); |
| 74 | + auto ret = svr.listen(host, port); |
37 | 75 |
|
38 |
| - return 0; |
| 76 | + return ret ? 0 : 1; |
39 | 77 | }
|
0 commit comments