RAVENNAKIT
Loading...
Searching...
No Matches
http_client.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: AGPL-3.0-or-later
2/*
3 * Project: RAVENNAKIT (RAVENNA / AES67 / ST2110-30 SDK)
4 * Copyright (c) 2024-2025 Sound on Digital
5 *
6 * This file is part of RAVENNAKIT.
7 *
8 * RAVENNAKIT is dual-licensed:
9 * 1) Under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version (the "AGPL License"); and
12 * 2) Under a commercial license from Sound on Digital, for customers who
13 * cannot (or do not wish to) comply with the AGPL License terms.
14 *
15 * If you obtained this file under the AGPL License, you may redistribute it
16 * and/or modify it under the terms of the AGPL License. See the LICENSE
17 * file in the project root for details.
18 *
19 * For commercial licensing, support, and other inquiries, please visit:
20 *
21 * https://ravennakit.com
22 *
23 */
24
25#pragma once
26
28
29#include <boost/asio.hpp>
30#include <boost/url.hpp>
31
32#include <string>
33#include <queue>
34
35namespace rav {
36
37namespace http = boost::beast::http;
38using tcp = boost::asio::ip::tcp;
39
41 public:
42 virtual ~HttpClientBase() = default;
43
45 static constexpr auto k_default_port = "80";
46
47 using Request = http::request<http::string_body>;
48 using Response = http::response<http::string_body>;
49
51 using ResponseCallback = std::function<void(boost::system::result<http::response<http::string_body>> response)>;
52
57 virtual void set_host(const boost::urls::url& url) = 0;
58
63 virtual void set_host(std::string_view url) = 0;
64
70 virtual void set_host(std::string_view host, std::string_view service) = 0;
71
79 virtual void get_async(std::string_view target, ResponseCallback callback) = 0;
80
89 virtual void post_async(std::string_view target, std::string body, ResponseCallback callback, std::string_view content_type) = 0;
90
96 virtual void delete_async(std::string_view target, ResponseCallback callback) = 0;
97
106 virtual void request_async(
107 http::verb method, std::string_view target, std::string body, std::string_view content_type, ResponseCallback callback
108 ) = 0;
109
113 virtual void cancel_outstanding_requests() = 0;
114
118 [[nodiscard]] virtual const std::string& get_host() const = 0;
119
123 [[nodiscard]] virtual const std::string& get_service() const = 0;
124};
125
130 public:
136 explicit HttpClient(boost::asio::io_context& io_context, std::chrono::milliseconds timeout_seconds = std::chrono::seconds(30));
137
145 boost::asio::io_context& io_context, std::string_view url, std::chrono::milliseconds timeout_seconds = std::chrono::seconds(30)
146 );
147
155 boost::asio::io_context& io_context, const boost::urls::url& url,
156 std::chrono::milliseconds timeout_seconds = std::chrono::seconds(30)
157 );
158
166 boost::asio::io_context& io_context, const boost::asio::ip::tcp::endpoint& endpoint,
167 std::chrono::milliseconds timeout_seconds = std::chrono::seconds(30)
168 );
169
178 boost::asio::io_context& io_context, const boost::asio::ip::address& address, uint16_t port,
179 std::chrono::milliseconds timeout_seconds = std::chrono::seconds(30)
180 );
181
182 ~HttpClient() override;
183
184 HttpClient(const HttpClient&) = delete;
185 HttpClient& operator=(const HttpClient&) = delete;
188
192 void set_host(const boost::urls::url& url) override;
193
197 void set_host(std::string_view url) override;
198
202 void set_host(std::string_view host, std::string_view service) override;
203
207 void get_async(std::string_view target, ResponseCallback callback) override;
208
212 void post_async(std::string_view target, std::string body, ResponseCallback callback, std::string_view content_type) override;
213
218 http::verb method, std::string_view target, std::string body, std::string_view content_type, ResponseCallback callback
219 ) override;
220
224 void delete_async(std::string_view target, ResponseCallback callback) override;
225
230
234 [[nodiscard]] const std::string& get_host() const override;
235
239 [[nodiscard]] const std::string& get_service() const override;
240
241 private:
245 class Session: public std::enable_shared_from_this<Session> {
246 public:
247 enum class State { disconnected, resolving, connecting, connected, waiting_for_send, waiting_for_response };
248 explicit Session(boost::asio::io_context& io_context, HttpClient* owner, std::chrono::milliseconds timeout_seconds);
249
250 void send_requests();
251 void clear_owner();
252
253 ResponseCallback callback_;
254
255 private:
256 HttpClient* owner_ = nullptr;
257 std::chrono::milliseconds timeout_seconds_ = std::chrono::seconds(30);
258 boost::asio::ip::tcp::resolver resolver_;
259 boost::beast::tcp_stream stream_;
260 http::request<http::string_body> request_;
261 http::response<http::string_body> response_;
262 boost::beast::flat_buffer buffer_;
263 State state_ = State::disconnected;
264
265 void async_connect();
266 void async_send();
267 void on_resolve(const boost::beast::error_code& ec, const tcp::resolver::results_type& results);
268 void on_connect(const boost::beast::error_code& ec, const tcp::resolver::results_type::endpoint_type&);
269 void on_write(const boost::beast::error_code& ec, std::size_t bytes_transferred);
270 void on_read(boost::beast::error_code ec, std::size_t bytes_transferred);
271
272 bool take_next_request();
273 };
274
275 boost::asio::io_context& io_context_;
276 std::chrono::milliseconds timeout_seconds_ = std::chrono::seconds(30);
277 std::string host_;
278 std::string service_;
279 std::queue<std::pair<http::request<http::string_body>, ResponseCallback>> requests_;
280 std::shared_ptr<Session> session_;
281};
282
283} // namespace rav
static constexpr auto k_default_port
When no port is specified in the urls, the default port is used.
virtual void set_host(std::string_view host, std::string_view service)=0
Sets the host to connect to.
virtual const std::string & get_service() const =0
std::function< void(boost::system::result< http::response< http::string_body > > response)> ResponseCallback
Callback type for async requests.
virtual ~HttpClientBase()=default
virtual void set_host(std::string_view url)=0
Sets the host to connect to.
virtual void cancel_outstanding_requests()=0
Clears all scheduled requests if there are any.
virtual void set_host(const boost::urls::url &url)=0
Sets the host to connect to.
http::response< http::string_body > Response
virtual void post_async(std::string_view target, std::string body, ResponseCallback callback, std::string_view content_type)=0
Asynchronous POST request to the target of the URL, or the root if no target is specified.
virtual void get_async(std::string_view target, ResponseCallback callback)=0
Asynchronous GET request.
virtual void request_async(http::verb method, std::string_view target, std::string body, std::string_view content_type, ResponseCallback callback)=0
Asynchronous request.
virtual const std::string & get_host() const =0
http::request< http::string_body > Request
virtual void delete_async(std::string_view target, ResponseCallback callback)=0
Asynchronous DELETE request to the target of the URL, or the root if no target is specified.
A high level wrapper around boost::beast for making HTTP requests.
void set_host(std::string_view host, std::string_view service) override
Sets the host to connect to.
HttpClient(boost::asio::io_context &io_context, const boost::urls::url &url, std::chrono::milliseconds timeout_seconds=std::chrono::seconds(30))
Constructs a new HttpClient using the given io_context and url.
void set_host(const boost::urls::url &url) override
Sets the host to connect to.
HttpClient(boost::asio::io_context &io_context, std::string_view url, std::chrono::milliseconds timeout_seconds=std::chrono::seconds(30))
Constructs a new HttpClient using the given io_context and url.
void delete_async(std::string_view target, ResponseCallback callback) override
Asynchronous DELETE request to the target of the URL, or the root if no target is specified.
HttpClient & operator=(HttpClient &&)=delete
HttpClient(boost::asio::io_context &io_context, const boost::asio::ip::address &address, uint16_t port, std::chrono::milliseconds timeout_seconds=std::chrono::seconds(30))
Constructs a new HttpClient using the given io_context and url.
~HttpClient() override
void get_async(std::string_view target, ResponseCallback callback) override
Asynchronous GET request.
const std::string & get_service() const override
void post_async(std::string_view target, std::string body, ResponseCallback callback, std::string_view content_type) override
Asynchronous POST request to the target of the URL, or the root if no target is specified.
HttpClient(const HttpClient &)=delete
HttpClient(boost::asio::io_context &io_context, const boost::asio::ip::tcp::endpoint &endpoint, std::chrono::milliseconds timeout_seconds=std::chrono::seconds(30))
Constructs a new HttpClient using the given io_context and url.
void cancel_outstanding_requests() override
Clears all scheduled requests if there are any.
void set_host(std::string_view url) override
Sets the host to connect to.
HttpClient(boost::asio::io_context &io_context, std::chrono::milliseconds timeout_seconds=std::chrono::seconds(30))
Constructs a new HttpClient using the given io_context, but no url.
void request_async(http::verb method, std::string_view target, std::string body, std::string_view content_type, ResponseCallback callback) override
Asynchronous request.
HttpClient & operator=(const HttpClient &)=delete
const std::string & get_host() const override
HttpClient(HttpClient &&)=delete
boost::asio::ip::tcp tcp