summaryrefslogtreecommitdiffstats
path: root/server/src/http_client.cppm
diff options
context:
space:
mode:
authorRutger Broekhoff2026-08-28 18:03:05 +0200
committerRutger Broekhoff2026-08-28 18:03:05 +0200
commit973aec43ea54bbf95b64fbcb636403401d1ca60e (patch)
tree41b7911c420766a9b463245b9296f44c5bf35258 /server/src/http_client.cppm
downloadroutemon-973aec43ea54bbf95b64fbcb636403401d1ca60e.tar.gz
routemon-973aec43ea54bbf95b64fbcb636403401d1ca60e.zip
Import from e4b104792206ee7ea64bf39c6b7d2c0c230f9d14
Diffstat (limited to 'server/src/http_client.cppm')
-rw-r--r--server/src/http_client.cppm62
1 files changed, 62 insertions, 0 deletions
diff --git a/server/src/http_client.cppm b/server/src/http_client.cppm
new file mode 100644
index 0000000..d5316d6
--- /dev/null
+++ b/server/src/http_client.cppm
@@ -0,0 +1,62 @@
1module;
2
3#include <boost/asio/connect.hpp>
4#include <boost/asio/ip/tcp.hpp>
5#include <boost/asio/ssl.hpp>
6#include <boost/beast/core.hpp>
7#include <boost/beast/http.hpp>
8
9export module routemon:http.client;
10
11export import :http.common;
12
13namespace net = boost::asio;
14namespace ssl = net::ssl;
15using tcp = net::ip::tcp;
16
17namespace routemon::http {
18
19 export class client {
20 net::io_context& ioc_;
21 ssl::context sslc_{ssl::context::tlsv12_client};
22 tcp::resolver resolver_;
23
24 public:
25 explicit client(net::io_context& ioc)
26 : ioc_{ioc}, resolver_{ioc}
27 {
28 sslc_.set_default_verify_paths();
29 sslc_.set_verify_mode(net::ssl::verify_peer | net::ssl::verify_fail_if_no_peer_cert);
30 }
31
32 template<class ReqBody>
33 auto do_request(bhttp::request<ReqBody>& req) -> bhttp::response<bhttp::dynamic_body> {
34 auto stream = ssl::stream<beast::tcp_stream>{ioc_, sslc_};
35
36 auto host = std::string{req.at(bhttp::field::host)};
37 if (!SSL_set_tlsext_host_name(stream.native_handle(), host.c_str())) {
38 throw beast::system_error(static_cast<int>(::ERR_get_error()),
39 net::error::get_ssl_category());
40 }
41 stream.set_verify_callback(ssl::host_name_verification(host));
42 auto const results = resolver_.resolve(host, "443");
43 beast::get_lowest_layer(stream).connect(results);
44 stream.handshake(ssl::stream_base::client);
45
46 req.set(bhttp::field::user_agent, "routemon/1.0");
47 bhttp::write(stream, req);
48
49 auto buffer = beast::flat_buffer{};
50 auto res = bhttp::response<bhttp::dynamic_body>{};
51 bhttp::read(stream, buffer, res);
52
53 auto ec = beast::error_code{};
54 stream.shutdown(ec);
55 if (ec != net::ssl::error::stream_truncated)
56 throw beast::system_error{ec};
57
58 return res;
59 }
60 };
61
62} // namespace routemon::http