src/detail/http_tunnel.cpp

100.0% Lines (2/2) 100.0% List of functions (1/1) 100.0% Branches (1/1)
http_tunnel.cpp
f(x) Functions (1)
Line Branch TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Mohammad Nejati
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/burl
8 //
9
10 #include "http_tunnel.hpp"
11
12 #include <boost/burl/error.hpp>
13
14 #include "base64.hpp"
15
16 #include <boost/capy/buffers/make_buffer.hpp>
17 #include <boost/capy/write.hpp>
18 #include <boost/http/field.hpp>
19 #include <boost/http/method.hpp>
20 #include <boost/http/request.hpp>
21 #include <boost/http/response_parser.hpp>
22 #include <boost/http/status.hpp>
23
24 #include <string>
25
26 namespace boost
27 {
28 namespace burl
29 {
30 namespace detail
31 {
32
33 capy::io_task<>
34
1/1
✓ Branch 1 taken 13 times.
13x open_http_tunnel(
35 capy::any_stream stream,
36 std::string_view target_host,
37 std::string_view target_port,
38 urls::url_view proxy)
39 {
40 std::string host_port(target_host);
41 host_port += ':';
42 host_port += target_port;
43
44 http::request req(http::method::connect, host_port);
45 req.set(http::field::host, host_port);
46 req.set(http::field::proxy_connection, "keep-alive");
47
48 if(proxy.has_userinfo())
49 {
50 std::string value = "Basic ";
51 detail::base64_encode(value, proxy.encoded_userinfo().decode());
52 req.set(http::field::proxy_authorization, value);
53 }
54
55 if(auto [ec, n] =
56 co_await capy::write(stream, capy::make_buffer(req.buffer()));
57 ec)
58 co_return ec;
59
60 auto parser_cfg = http::make_parser_config(http::parser_config{ false });
61 http::response_parser parser(parser_cfg);
62 parser.reset();
63 parser.start();
64 if(auto [ec] = co_await parser.read_header(stream); ec)
65 co_return { error::proxy_connect_failed };
66
67 auto status = parser.get().status();
68 if(status == http::status::proxy_authentication_required)
69 co_return { error::proxy_auth_failed };
70 if(to_status_class(status) != http::status_class::successful)
71 co_return { error::proxy_connect_failed };
72
73 co_return {};
74 26x }
75
76 } // namespace detail
77 } // namespace burl
78 } // namespace boost
79