1  
//
1  
//
2  
// Copyright (c) 2026 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2026 Vinnie Falco (vinnie.falco@gmail.com)
3  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
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)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/cppalliance/http
7  
// Official repository: https://github.com/cppalliance/http
8  
//
8  
//
9  

9  

10  
#ifndef BOOST_HTTP_SERVER_WORKER_HPP
10  
#ifndef BOOST_HTTP_SERVER_WORKER_HPP
11  
#define BOOST_HTTP_SERVER_WORKER_HPP
11  
#define BOOST_HTTP_SERVER_WORKER_HPP
12  

12  

13  
#include <boost/http/detail/config.hpp>
13  
#include <boost/http/detail/config.hpp>
14  
#include <boost/capy/io/any_read_stream.hpp>
14  
#include <boost/capy/io/any_read_stream.hpp>
15  
#include <boost/capy/task.hpp>
15  
#include <boost/capy/task.hpp>
16  
#include <boost/http/config.hpp>
16  
#include <boost/http/config.hpp>
17  
#include <boost/http/request_parser.hpp>
17  
#include <boost/http/request_parser.hpp>
18  
#include <boost/http/serializer.hpp>
18  
#include <boost/http/serializer.hpp>
19  
#include <boost/http/server/router.hpp>
19  
#include <boost/http/server/router.hpp>
20  

20  

21  
namespace boost {
21  
namespace boost {
22  
namespace http {
22  
namespace http {
23  

23  

24  
/** Reusable HTTP request/response processing logic.
24  
/** Reusable HTTP request/response processing logic.
25  

25  

26  
    This class provides the core HTTP processing loop: reading
26  
    This class provides the core HTTP processing loop: reading
27  
    requests, dispatching them through a router, and sending
27  
    requests, dispatching them through a router, and sending
28  
    responses. It is designed as a mix-in base class for use
28  
    responses. It is designed as a mix-in base class for use
29  
    with @ref corosio::tcp_server.
29  
    with @ref corosio::tcp_server.
30  

30  

31  
    @par Usage with tcp_server
31  
    @par Usage with tcp_server
32  

32  

33  
    To use this class, derive a custom worker from both
33  
    To use this class, derive a custom worker from both
34  
    @ref corosio::tcp_server::worker_base and `http_worker`.
34  
    @ref corosio::tcp_server::worker_base and `http_worker`.
35  
    The derived class must:
35  
    The derived class must:
36  

36  

37  
    @li Construct `http_worker` with a router and configurations
37  
    @li Construct `http_worker` with a router and configurations
38  
    @li Initialize the @ref stream member before calling
38  
    @li Initialize the @ref stream member before calling
39  
        @ref do_http_session
39  
        @ref do_http_session
40  
    @li Wire the parser and serializer to the socket by setting
40  
    @li Wire the parser and serializer to the socket by setting
41  
        `rp.req_body` and `rp.res_body`
41  
        `rp.req_body` and `rp.res_body`
42  

42  

43  
    @par Example
43  
    @par Example
44  
    @code
44  
    @code
45  
    struct my_worker
45  
    struct my_worker
46  
        : tcp_server::worker_base
46  
        : tcp_server::worker_base
47  
        , http_worker
47  
        , http_worker
48  
    {
48  
    {
49  
        corosio::tcp_socket sock;
49  
        corosio::tcp_socket sock;
50  

50  

51  
        my_worker(
51  
        my_worker(
52  
            corosio::io_context& ctx,
52  
            corosio::io_context& ctx,
53  
            http::router<route_params> const& router,
53  
            http::router<route_params> const& router,
54  
            http::shared_parser_config parser_cfg,
54  
            http::shared_parser_config parser_cfg,
55  
            http::shared_serializer_config serializer_cfg)
55  
            http::shared_serializer_config serializer_cfg)
56  
            : http_worker(router, parser_cfg, serializer_cfg)
56  
            : http_worker(router, parser_cfg, serializer_cfg)
57  
            , sock(ctx)
57  
            , sock(ctx)
58  
        {
58  
        {
59  
            sock.open();
59  
            sock.open();
60  
            rp.req_body = capy::any_buffer_source(parser.source_for(sock));
60  
            rp.req_body = capy::any_buffer_source(parser.source_for(sock));
61  
            rp.res_body = capy::any_buffer_sink(serializer.sink_for(sock));
61  
            rp.res_body = capy::any_buffer_sink(serializer.sink_for(sock));
62  
            stream = capy::any_read_stream(&sock);
62  
            stream = capy::any_read_stream(&sock);
63  
        }
63  
        }
64  

64  

65  
        corosio::tcp_socket& socket() override { return sock; }
65  
        corosio::tcp_socket& socket() override { return sock; }
66  

66  

67  
        void run(launcher launch) override
67  
        void run(launcher launch) override
68  
        {
68  
        {
69  
            launch(sock.get_executor(), do_http_session());
69  
            launch(sock.get_executor(), do_http_session());
70  
        }
70  
        }
71  
    };
71  
    };
72  
    @endcode
72  
    @endcode
73  

73  

74  
    @par Thread Safety
74  
    @par Thread Safety
75  
    Distinct objects: Safe.
75  
    Distinct objects: Safe.
76  
    Shared objects: Unsafe.
76  
    Shared objects: Unsafe.
77  

77  

78  
    @see corosio::tcp_server, http_server
78  
    @see corosio::tcp_server, http_server
79  
*/
79  
*/
80  
class BOOST_HTTP_DECL http_worker
80  
class BOOST_HTTP_DECL http_worker
81  
{
81  
{
82  
public:
82  
public:
83  
    http::router<route_params> fr;
83  
    http::router<route_params> fr;
84  
    http::route_params rp;
84  
    http::route_params rp;
85  
    capy::any_read_stream stream;
85  
    capy::any_read_stream stream;
86  
    http::request_parser parser;
86  
    http::request_parser parser;
87  
    http::serializer serializer;
87  
    http::serializer serializer;
88  

88  

89  
    /** Construct an HTTP worker.
89  
    /** Construct an HTTP worker.
90  

90  

91  
        @param fr_ The router for dispatching requests to handlers.
91  
        @param fr_ The router for dispatching requests to handlers.
92  
        @param parser_cfg Shared configuration for the request parser.
92  
        @param parser_cfg Shared configuration for the request parser.
93  
        @param serializer_cfg Shared configuration for the response
93  
        @param serializer_cfg Shared configuration for the response
94  
            serializer.
94  
            serializer.
95  
    */
95  
    */
96  
    template<capy::WriteStream Stream>
96  
    template<capy::WriteStream Stream>
97  
    http_worker(
97  
    http_worker(
98  
        Stream& stream_,
98  
        Stream& stream_,
99  
        http::router<route_params> fr_,
99  
        http::router<route_params> fr_,
100  
        http::shared_parser_config parser_cfg,
100  
        http::shared_parser_config parser_cfg,
101  
        http::shared_serializer_config serializer_cfg)
101  
        http::shared_serializer_config serializer_cfg)
102  
        : fr(std::move(fr_))
102  
        : fr(std::move(fr_))
103  
        , stream(&stream_)
103  
        , stream(&stream_)
104  
        , parser(parser_cfg)
104  
        , parser(parser_cfg)
105  
        , serializer(serializer_cfg)
105  
        , serializer(serializer_cfg)
106  
        {
106  
        {
107  
            serializer.set_message(rp.res);
107  
            serializer.set_message(rp.res);
108  
            rp.req_body = capy::any_buffer_source(parser.source_for(stream_));
108  
            rp.req_body = capy::any_buffer_source(parser.source_for(stream_));
109  
            rp.res_body = capy::any_buffer_sink(serializer.sink_for(stream_));
109  
            rp.res_body = capy::any_buffer_sink(serializer.sink_for(stream_));
110  
        }
110  
        }
111  

111  

112  
    /** Handle an HTTP session.
112  
    /** Handle an HTTP session.
113  

113  

114  
        This coroutine reads HTTP requests, dispatches them through
114  
        This coroutine reads HTTP requests, dispatches them through
115  
        the router, and sends responses until the connection is
115  
        the router, and sends responses until the connection is
116  
        closed or an error occurs. The stream data member must be
116  
        closed or an error occurs. The stream data member must be
117  
        initialized before calling this function.
117  
        initialized before calling this function.
118  

118  

119  
        @return An awaitable that completes when the session ends.
119  
        @return An awaitable that completes when the session ends.
120  
    */
120  
    */
121  
    capy::task<void>
121  
    capy::task<void>
122  
    do_http_session();
122  
    do_http_session();
123  
};
123  
};
124  

124  

125  
} // http
125  
} // http
126  
} // boost
126  
} // boost
127  

127  

128  
#endif
128  
#endif