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 #include <boost/burl/message_reader.hpp>
14 #include <boost/burl/response_parser.hpp>
15 #include <boost/burl/request_head.hpp>
16
17 #include "base64.hpp"
18 #include "effective_port.hpp"
19
20 #include <boost/capy/buffers/make_buffer.hpp>
21 #include <boost/capy/write.hpp>
22
23 #include <string>
24
25 namespace boost
26 {
27 namespace burl
28 {
29 namespace detail
30 {
31
32 capy::io_task<>
33
1/1
✓ Branch 1 taken 15 times.
15x open_http_tunnel(
34 capy::any_stream stream,
35 urls::url_view target,
36 urls::url_view proxy)
37 {
38 std::string host_port(target.encoded_host());
39 host_port += ':';
40 host_port += effective_port(target);
41
42 request_head req(http::method::connect, host_port);
43 req.set(http::field::host, host_port);
44 req.set(http::field::proxy_connection, "keep-alive");
45
46 if(proxy.has_userinfo())
47 {
48 std::string value = "Basic ";
49 detail::base64_encode(value, proxy.encoded_userinfo().decode());
50 req.set(http::field::proxy_authorization, value);
51 }
52
53 std::error_code ec;
54
55 std::tie(ec, std::ignore) = co_await capy::write(
56 stream, capy::make_buffer(req.buffer()));
57 if(ec)
58 co_return ec;
59
60 response_parser parser(response_parser::config{});
61 parser.start();
62 std::tie(ec) = co_await message_reader{
63 &stream, &parser }.read_header();
64 if(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 30x }
75
76 } // namespace detail
77 } // namespace burl
78 } // namespace boost
79