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  
#include <boost/http/server/http_worker.hpp>
10  
#include <boost/http/server/http_worker.hpp>
11  
#include <boost/http/error.hpp>
11  
#include <boost/http/error.hpp>
12  
#include <boost/url/parse.hpp>
12  
#include <boost/url/parse.hpp>
13  
#include <iostream>
13  
#include <iostream>
14  

14  

15  
namespace boost {
15  
namespace boost {
16  
namespace http {
16  
namespace http {
17  

17  

18  
capy::task<void>
18  
capy::task<void>
19  
http_worker::
19  
http_worker::
20  
do_http_session()
20  
do_http_session()
21  
{
21  
{
22  
    struct guard
22  
    struct guard
23  
    {
23  
    {
24  
        http_worker& self;
24  
        http_worker& self;
25  

25  

26  
        guard(http_worker& self_)
26  
        guard(http_worker& self_)
27  
            : self(self_)
27  
            : self(self_)
28  
        {
28  
        {
29  
        }
29  
        }
30  

30  

31  
        ~guard()
31  
        ~guard()
32  
        {
32  
        {
33  
            self.parser.reset();
33  
            self.parser.reset();
34  
            self.parser.start();
34  
            self.parser.start();
35  
            self.rp.session_data.clear();
35  
            self.rp.session_data.clear();
36  
        }
36  
        }
37  
    };
37  
    };
38  

38  

39  
    guard g(*this); // clear things when session ends
39  
    guard g(*this); // clear things when session ends
40  

40  

41  
    // read request, send response loop
41  
    // read request, send response loop
42  
    for(;;)
42  
    for(;;)
43  
    {
43  
    {
44  
        parser.reset();
44  
        parser.reset();
45  
        parser.start();
45  
        parser.start();
46  
        rp.session_data.clear();
46  
        rp.session_data.clear();
47  

47  

48  
        // Read HTTP request header
48  
        // Read HTTP request header
49  
        auto [ec] = co_await parser.read_header(stream);
49  
        auto [ec] = co_await parser.read_header(stream);
50  
        if(ec)
50  
        if(ec)
51  
        {
51  
        {
52  
            std::cerr << "read_header error: " << ec.message() << "\n";
52  
            std::cerr << "read_header error: " << ec.message() << "\n";
53  
            break;
53  
            break;
54  
        }
54  
        }
55  

55  

56  
        // Process headers and dispatch
56  
        // Process headers and dispatch
57  
        // Set up Request and Response objects
57  
        // Set up Request and Response objects
58  
        rp.req = parser.get();
58  
        rp.req = parser.get();
59  
        rp.route_data.clear();
59  
        rp.route_data.clear();
60  
        rp.res.set_start_line(
60  
        rp.res.set_start_line(
61  
            http::status::ok, rp.req.version());
61  
            http::status::ok, rp.req.version());
62  
        rp.res.set_keep_alive(rp.req.keep_alive());
62  
        rp.res.set_keep_alive(rp.req.keep_alive());
63  
        serializer.reset();
63  
        serializer.reset();
64  

64  

65  
        // Parse the URL
65  
        // Parse the URL
66  
        {
66  
        {
67  
            auto rv = urls::parse_uri_reference(rp.req.target());
67  
            auto rv = urls::parse_uri_reference(rp.req.target());
68  
            if(rv.has_error())
68  
            if(rv.has_error())
69  
            {
69  
            {
70  
                rp.status(http::status::bad_request);
70  
                rp.status(http::status::bad_request);
71  
            }
71  
            }
72  
            rp.url = rv.value();
72  
            rp.url = rv.value();
73  
        }
73  
        }
74  

74  

75  
        {
75  
        {
76  
            auto rv = co_await fr.dispatch(rp.req.method(), rp.url, rp);
76  
            auto rv = co_await fr.dispatch(rp.req.method(), rp.url, rp);
 
77 +

 
78 +
            if(rv.what() == route_what::close)
 
79 +
                break;
 
80 +

 
81 +
            if(rv.what() == route_what::next)
 
82 +
            {
 
83 +
                rp.status(http::status::not_found);
 
84 +
                (void)(co_await rp.send());
 
85 +
            }
 
86 +

77  
            if(rv.failed())
87  
            if(rv.failed())
78  
            {
88  
            {
79 -
                // VFALCO log rv.error()
89 +
                rp.status(http::status::internal_server_error);
80 -
                break;
90 +
                (void)(co_await rp.send());
81  
            }
91  
            }
82  

92  

83  
            if(! rp.res.keep_alive())
93  
            if(! rp.res.keep_alive())
84  
                break;
94  
                break;
85  
        }
95  
        }
86  
    }
96  
    }
87  
}
97  
}
88  

98  

89  
} // http
99  
} // http
90  
} // boost
100  
} // boost