-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
94 lines (79 loc) · 3.09 KB
/
Copy pathmain.cpp
File metadata and controls
94 lines (79 loc) · 3.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <iostream>
#include <string>
#include <string_view>
#include <thread>
constexpr std::string_view kPage = R"HTML(<!doctype html>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>James Lim</title>
<h1>James Lim</h1>
<p>I write C++</p>
<p>
<a href="https://github.com/lim-james">GitHub</a> ·
<a href="https://www.linkedin.com/in/jameslimbj">LinkedIn</a>
</p>)HTML";
namespace {
boost::beast::http::response<boost::beast::http::string_body> make_response(
const boost::beast::http::request<boost::beast::http::string_body>& request
) {
boost::beast::http::response<boost::beast::http::string_body> response;
response.version(request.version());
response.keep_alive(request.keep_alive());
response.set(boost::beast::http::field::server, "beast");
const bool is_head = request.method() == boost::beast::http::verb::head;
if (request.method() != boost::beast::http::verb::get && !is_head) {
response.result(boost::beast::http::status::method_not_allowed);
response.set(boost::beast::http::field::allow, "GET, HEAD");
response.set(boost::beast::http::field::content_type, "text/plain");
response.body() = "method not allowed\n";
} else if (request.target() != "/" && request.target() != "/index.html") {
response.result(boost::beast::http::status::not_found);
response.set(boost::beast::http::field::content_type, "text/plain");
response.body() = "not found\n";
} else {
response.result(boost::beast::http::status::ok);
response.set(boost::beast::http::field::content_type, "text/html; charset=utf-8");
response.body() = kPage;
}
const auto len = response.body().size();
response.prepare_payload();
if (is_head) {
response.body().clear();
response.content_length(len);
}
return response;
}
void handle_session(boost::asio::ip::tcp::socket socket) {
boost::beast::error_code error_code;
boost::beast::flat_buffer buffer;
for (;;) {
boost::beast::http::request<boost::beast::http::string_body> request;
boost::beast::http::read(socket, buffer, request, error_code);
if (error_code) break;
auto response = make_response(request);
const bool keep = response.keep_alive();
boost::beast::http::write(socket, response, error_code);
if (error_code || !keep) break;
}
socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, error_code);
}
} // namespace
int main(int argc, char** argv) {
try {
const auto addr = boost::asio::ip::make_address(argc > 1 ? argv[1] : "127.0.0.1");
const auto port = static_cast<unsigned short>(argc > 2 ? std::stoi(argv[2]) : 8080);
boost::asio::io_context ioc{1};
boost::asio::ip::tcp::acceptor acceptor{ioc, {addr, port}};
std::cerr << "listening on " << addr << ":" << port << "\n";
for (;;) {
boost::asio::ip::tcp::socket socket{ioc};
acceptor.accept(socket);
std::thread(handle_session, std::move(socket)).detach();
}
} catch (const std::exception& e) {
std::cerr << "fatal: " << e.what() << "\n";
return 1;
}
}