src/http_server.cpp

0.0% Lines (0/37) 0.0% List of functions (0/7) 0.0% Branches (0/18)
http_server.cpp
f(x) Functions (7)
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/cppalliance/beast2
8 //
9
10 #include <boost/beast2/http_server.hpp>
11 #include <boost/beast2/http_worker.hpp>
12 #include <boost/capy/task.hpp>
13 #include <boost/capy/cond.hpp>
14 #include <boost/capy/ex/strand.hpp>
15 #include <boost/capy/io/any_read_stream.hpp>
16 #include <boost/http/io/any_buffer_sink.hpp>
17 #include <boost/http/io/any_buffer_source.hpp>
18 #include <boost/http/request_parser.hpp>
19 #include <boost/http/response.hpp>
20 #include <boost/http/server/router.hpp>
21 #include <boost/http/serializer.hpp>
22 #include <boost/http/string_body.hpp>
23 #include <boost/http/error.hpp>
24 #include <boost/url/parse.hpp>
25 #include <iostream>
26 #include <tuple>
27
28 namespace boost {
29 namespace beast2 {
30
31 struct http_server::impl
32 {
33 http::router<http::route_params> router;
34 http::shared_parser_config parser_cfg;
35 http::shared_serializer_config serializer_cfg;
36
37 ✗ impl(http::router<http::route_params> r)
38 ✗ : router(std::move(r))
39 {
40 ✗ }
41 };
42
43 // Each worker owns its own socket and parser/serializer state,
44 // allowing concurrent connection handling without synchronization.
45 struct http_server::
46 worker
47 : tcp_server::worker_base
48 , http_worker
49 {
50 corosio::io_context& ctx;
51 capy::strand<corosio::io_context::executor_type> strand;
52 corosio::tcp_socket sock;
53
54 ✗ worker(
55 corosio::io_context& ctx_,
56 http_server* srv_)
57 ✗ : http_worker(
58 ✗ srv_->impl_->router,
59 ✗ srv_->impl_->parser_cfg,
60 ✗ srv_->impl_->serializer_cfg)
61 ✗ , ctx(ctx_)
62 ✗ , strand(ctx_.get_executor())
63 ✗ , sock(ctx_)
64 {
65 ✗ std::ignore = sock.open();
66
67 ✗ rp.req_body = http::any_buffer_source(parser.source_for(sock));
68 ✗ rp.res_body = http::any_buffer_sink(serializer.sink_for(sock));
69 ✗ stream = capy::any_read_stream(&sock);
70 ✗ }
71
72 ✗ corosio::tcp_socket& socket() override
73 {
74 ✗ return sock;
75 }
76
77 ✗ void run(launcher launch) override
78 {
79 ✗ launch(ctx.get_executor(), do_session());
80 ✗ }
81
82 capy::task<void>
83 ✗ do_session()
84 {
85 co_await do_http_session();
86
87 std::ignore = sock.shutdown(corosio::tcp_socket::shutdown_both); // VFALCO too wordy
88 ✗ }
89 };
90
91 ✗ http_server::
92 ~http_server()
93 {
94 ✗ delete impl_;
95 ✗ }
96
97 ✗ http_server::
98 http_server(
99 corosio::io_context& ctx,
100 std::size_t num_workers,
101 http::router<http::route_params> router,
102 http::shared_parser_config parser_cfg,
103 ✗ http::shared_serializer_config serializer_cfg)
104 : tcp_server(ctx, ctx.get_executor())
105 ✗ , impl_(new impl(std::move(router)))
106 {
107 ✗ impl_->parser_cfg = std::move(parser_cfg);
108 ✗ impl_->serializer_cfg = std::move(serializer_cfg);
109
110 ✗ std::vector<std::unique_ptr<tcp_server::worker_base>> workers;
111 ✗ workers.reserve(num_workers);
112 ✗ for(std::size_t i = 0; i < num_workers; ++i)
113 ✗ workers.push_back(std::make_unique<worker>(ctx, this));
114 ✗ set_workers(std::move(workers));
115 ✗ }
116
117 } // beast2
118 } // boost
119