src/https_server.cpp

0.0% Lines (0/36) 0.0% List of functions (0/7) 0.0% Branches (0/15)
https_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/https_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/corosio/openssl_stream.hpp>
17 #include <boost/http/io/any_buffer_sink.hpp>
18 #include <boost/http/io/any_buffer_source.hpp>
19 #include <boost/http/request_parser.hpp>
20 #include <boost/http/response.hpp>
21 #include <boost/http/server/router.hpp>
22 #include <boost/http/serializer.hpp>
23 #include <boost/http/string_body.hpp>
24 #include <boost/http/error.hpp>
25 #include <boost/url/parse.hpp>
26 #include <iostream>
27 #include <memory>
28 #include <tuple>
29
30 namespace boost {
31 namespace beast2 {
32
33 struct https_server::impl
34 {
35 corosio::tls_context tls_ctx;
36 http::router<http::route_params> router;
37 http::shared_parser_config parser_cfg;
38 http::shared_serializer_config serializer_cfg;
39
40 ✗ impl(
41 corosio::tls_context tc,
42 http::router<http::route_params> r)
43 ✗ : tls_ctx(std::move(tc))
44 ✗ , router(std::move(r))
45 {
46 ✗ }
47 };
48
49 struct https_server::
50 worker
51 : tcp_server::worker_base
52 , http_worker
53 {
54 corosio::io_context& ctx;
55 capy::strand<corosio::io_context::executor_type> strand;
56 corosio::tcp_socket sock;
57 corosio::tls_context tls_ctx;
58 std::unique_ptr<corosio::openssl_stream> ssl;
59
60 ✗ worker(
61 corosio::io_context& ctx_,
62 https_server* srv_)
63 ✗ : http_worker(
64 ✗ srv_->impl_->router,
65 ✗ srv_->impl_->parser_cfg,
66 ✗ srv_->impl_->serializer_cfg)
67 ✗ , ctx(ctx_)
68 ✗ , strand(ctx_.get_executor())
69 ✗ , sock(ctx_)
70 ✗ , tls_ctx(srv_->impl_->tls_ctx)
71 {
72 ✗ std::ignore = sock.open();
73 ✗ }
74
75 ✗ corosio::tcp_socket& socket() override
76 {
77 ✗ return sock;
78 }
79
80 ✗ void run(launcher launch) override
81 {
82 ✗ launch(ctx.get_executor(), do_session());
83 ✗ }
84
85 capy::task<void>
86 ✗ do_session()
87 {
88 // Create TLS stream wrapping the socket
89 ssl = std::make_unique<corosio::openssl_stream>(&sock, tls_ctx);
90
91 // Perform TLS handshake as server
92 auto [hs_ec] = co_await ssl->handshake(corosio::tls_role::server);
93 if(hs_ec)
94 {
95 std::cerr << "TLS handshake error: " << hs_ec.message() << "\n";
96 std::ignore = sock.shutdown(corosio::tcp_socket::shutdown_both);
97 ssl.reset();
98 co_return;
99 }
100
101 // Wire parser and serializer to the TLS stream
102 rp.req_body = http::any_buffer_source(parser.source_for(*ssl));
103 rp.res_body = http::any_buffer_sink(serializer.sink_for(*ssl));
104 stream = capy::any_read_stream(ssl.get());
105
106 // Process HTTP requests over TLS
107 co_await do_http_session();
108
109 // Perform TLS shutdown
110 auto [shut_ec] = co_await ssl->shutdown();
111 if(shut_ec)
112 {
113 // TLS shutdown errors are common (peer may close abruptly)
114 }
115
116 // Clean up TLS stream before TCP shutdown
117 ssl.reset();
118
119 std::ignore = sock.shutdown(corosio::tcp_socket::shutdown_both);
120 ✗ }
121 };
122
123 ✗ https_server::
124 ~https_server()
125 {
126 ✗ delete impl_;
127 ✗ }
128
129 ✗ https_server::
130 https_server(
131 corosio::io_context& ctx,
132 std::size_t num_workers,
133 corosio::tls_context tls_ctx,
134 http::router<http::route_params> router,
135 http::shared_parser_config parser_cfg,
136 ✗ http::shared_serializer_config serializer_cfg)
137 : tcp_server(ctx, ctx.get_executor())
138 ✗ , impl_(new impl(std::move(tls_ctx), std::move(router)))
139 {
140 ✗ impl_->parser_cfg = std::move(parser_cfg);
141 ✗ impl_->serializer_cfg = std::move(serializer_cfg);
142
143 ✗ std::vector<std::unique_ptr<tcp_server::worker_base>> workers;
144 ✗ workers.reserve(num_workers);
145 ✗ for(std::size_t i = 0; i < num_workers; ++i)
146 ✗ workers.push_back(std::make_unique<worker>(ctx, this));
147 ✗ set_workers(std::move(workers));
148 ✗ }
149
150 } // beast2
151 } // boost
152