Line data Source code
1 : //
2 : // Copyright (c) 2026 Vinnie Falco (vinnie.falco@gmail.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/http
8 : //
9 :
10 : #ifndef BOOST_HTTP_SERVER_WORKER_HPP
11 : #define BOOST_HTTP_SERVER_WORKER_HPP
12 :
13 : #include <boost/http/detail/config.hpp>
14 : #include <boost/capy/io/any_read_stream.hpp>
15 : #include <boost/capy/task.hpp>
16 : #include <boost/http/config.hpp>
17 : #include <boost/http/request_parser.hpp>
18 : #include <boost/http/serializer.hpp>
19 : #include <boost/http/server/router.hpp>
20 :
21 : namespace boost {
22 : namespace http {
23 :
24 : /** Reusable HTTP request/response processing logic.
25 :
26 : This class provides the core HTTP processing loop: reading
27 : requests, dispatching them through a router, and sending
28 : responses. It is designed as a mix-in base class for use
29 : with @ref corosio::tcp_server.
30 :
31 : @par Usage with tcp_server
32 :
33 : To use this class, derive a custom worker from both
34 : @ref corosio::tcp_server::worker_base and `http_worker`.
35 : The derived class must:
36 :
37 : @li Construct `http_worker` with a router and configurations
38 : @li Initialize the @ref stream member before calling
39 : @ref do_http_session
40 : @li Wire the parser and serializer to the socket by setting
41 : `rp.req_body` and `rp.res_body`
42 :
43 : @par Example
44 : @code
45 : struct my_worker
46 : : tcp_server::worker_base
47 : , http_worker
48 : {
49 : corosio::tcp_socket sock;
50 :
51 : my_worker(
52 : corosio::io_context& ctx,
53 : http::router<route_params> const& router,
54 : http::shared_parser_config parser_cfg,
55 : http::shared_serializer_config serializer_cfg)
56 : : http_worker(router, parser_cfg, serializer_cfg)
57 : , sock(ctx)
58 : {
59 : sock.open();
60 : rp.req_body = capy::any_buffer_source(parser.source_for(sock));
61 : rp.res_body = capy::any_buffer_sink(serializer.sink_for(sock));
62 : stream = capy::any_read_stream(&sock);
63 : }
64 :
65 : corosio::tcp_socket& socket() override { return sock; }
66 :
67 : void run(launcher launch) override
68 : {
69 : launch(sock.get_executor(), do_http_session());
70 : }
71 : };
72 : @endcode
73 :
74 : @par Thread Safety
75 : Distinct objects: Safe.
76 : Shared objects: Unsafe.
77 :
78 : @see corosio::tcp_server, http_server
79 : */
80 : class BOOST_HTTP_DECL http_worker
81 : {
82 : public:
83 : http::router<route_params> fr;
84 : http::route_params rp;
85 : capy::any_read_stream stream;
86 : http::request_parser parser;
87 : http::serializer serializer;
88 :
89 : /** Construct an HTTP worker.
90 :
91 : @param fr_ The router for dispatching requests to handlers.
92 : @param parser_cfg Shared configuration for the request parser.
93 : @param serializer_cfg Shared configuration for the response
94 : serializer.
95 : */
96 : template<capy::WriteStream Stream>
97 67 : http_worker(
98 : Stream& stream_,
99 : http::router<route_params> fr_,
100 : http::shared_parser_config parser_cfg,
101 : http::shared_serializer_config serializer_cfg)
102 67 : : fr(std::move(fr_))
103 67 : , stream(&stream_)
104 67 : , parser(parser_cfg)
105 134 : , serializer(serializer_cfg)
106 : {
107 67 : serializer.set_message(rp.res);
108 67 : rp.req_body = capy::any_buffer_source(parser.source_for(stream_));
109 67 : rp.res_body = capy::any_buffer_sink(serializer.sink_for(stream_));
110 67 : }
111 :
112 : /** Handle an HTTP session.
113 :
114 : This coroutine reads HTTP requests, dispatches them through
115 : the router, and sends responses until the connection is
116 : closed or an error occurs. The stream data member must be
117 : initialized before calling this function.
118 :
119 : @return An awaitable that completes when the session ends.
120 : */
121 : capy::task<void>
122 : do_http_session();
123 : };
124 :
125 : } // http
126 : } // boost
127 :
128 : #endif
|