29# define snprintf snprintf
32#include <asio/ssl/context.hpp>
33#include <restinio/http_headers.hpp>
34#include <restinio/message_builders.hpp>
46struct http_parser_settings;
64using HandlerCb = std::function<void(
const asio::error_code& ec)>;
65using BytesHandlerCb = std::function<void(
const asio::error_code& ec,
size_t bytes)>;
66using ConnectHandlerCb = std::function<void(
const asio::error_code& ec,
67 const asio::ip::tcp::endpoint& endpoint)>;
69using ssl_socket_t = restinio::impl::tls_socket_t;
70using socket_t = asio::ip::tcp::socket;
72class OPENDHT_PUBLIC
Url
76 Url(
const std::string& url);
78 std::string protocol {
"http"};
85 std::string toString()
const;
88class OPENDHT_PUBLIC
Connection :
public std::enable_shared_from_this<Connection>
91 Connection(asio::io_context& ctx,
const bool ssl =
true, std::shared_ptr<dht::Logger> l = {});
92 Connection(asio::io_context& ctx, std::shared_ptr<dht::crypto::Certificate> server_ca,
93 const dht::crypto::Identity& identity, std::shared_ptr<dht::Logger> l = {});
96 inline unsigned int id()
const {
return id_; };
99 void checkOcsp(
bool check =
true) { checkOcsp_ = check; }
101 void set_ssl_verification(
const std::string& hostname,
const asio::ssl::verify_mode verify_mode);
103 asio::streambuf& input();
104 std::istream& data() {
return istream_; }
106 std::string read_bytes(
size_t bytes = 0);
107 std::string read_until(
const char delim);
109 void async_connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, ConnectHandlerCb);
110 void async_handshake(HandlerCb cb);
111 void async_write(BytesHandlerCb cb);
112 void async_read_until(
const char* delim, BytesHandlerCb cb);
113 void async_read_until(
char delim, BytesHandlerCb cb);
114 void async_read(
size_t bytes, BytesHandlerCb cb);
115 void async_read_some(
size_t bytes, BytesHandlerCb cb);
117 void timeout(
const std::chrono::seconds timeout, HandlerCb cb = {});
123 T wrapCallabck(T cb)
const {
124 return [t=shared_from_this(),cb=std::move(cb)](
auto ...params) {
129 mutable std::mutex mutex_;
132 static std::atomic_uint ids_;
134 asio::io_context& ctx_;
135 std::unique_ptr<socket_t> socket_;
136 std::shared_ptr<asio::ssl::context> ssl_ctx_;
137 std::unique_ptr<ssl_socket_t> ssl_socket_;
139 asio::ip::tcp::endpoint endpoint_;
141 asio::streambuf write_buf_;
142 asio::streambuf read_buf_;
143 std::istream istream_;
145 std::unique_ptr<asio::steady_timer> timeout_timer_;
146 std::shared_ptr<dht::Logger> logger_;
147 bool checkOcsp_ {
false};
157 std::future<size_t> token;
158 std::shared_ptr<restinio::response_builder_t<restinio::chunked_output_t>> response;
167 using ResolverCb = std::function<void(
const asio::error_code& ec,
168 const std::vector<asio::ip::tcp::endpoint>& endpoints)>;
170 Resolver(asio::io_context& ctx,
const std::string& url, std::shared_ptr<dht::Logger> logger = {});
171 Resolver(asio::io_context& ctx,
const std::string& host,
const std::string& service,
172 const bool ssl =
false, std::shared_ptr<dht::Logger> logger = {});
175 Resolver(asio::io_context& ctx, std::vector<asio::ip::tcp::endpoint> endpoints,
176 const bool ssl =
false, std::shared_ptr<dht::Logger> logger = {});
177 Resolver(asio::io_context& ctx,
const std::string& url, std::vector<asio::ip::tcp::endpoint> endpoints,
178 std::shared_ptr<dht::Logger> logger = {});
182 inline const Url& get_url()
const {
186 void add_callback(ResolverCb cb, sa_family_t family = AF_UNSPEC);
188 std::shared_ptr<Logger> getLogger()
const {
193 void resolve(
const std::string& host,
const std::string& service);
195 mutable std::mutex mutex_;
198 asio::error_code ec_;
199 asio::ip::tcp::resolver resolver_;
200 std::shared_ptr<bool> destroyed_;
201 std::vector<asio::ip::tcp::endpoint> endpoints_;
203 bool completed_ {
false};
204 std::queue<ResolverCb> cbs_;
206 std::shared_ptr<dht::Logger> logger_;
213 unsigned status_code {0};
214 std::map<std::string, std::string> headers;
216 bool aborted {
false};
217 std::weak_ptr<Request> request;
220class OPENDHT_PUBLIC
Request :
public std::enable_shared_from_this<Request>
230 using OnStatusCb = std::function<void(
unsigned status_code)>;
231 using OnDataCb = std::function<void(
const char* at,
size_t length)>;
232 using OnStateChangeCb = std::function<void(State state,
const Response& response)>;
233 using OnJsonCb = std::function<void(Json::Value value,
const Response& response)>;
234 using OnDoneCb = std::function<void(
const Response& response)>;
237 Request(asio::io_context& ctx,
const std::string& url,
const Json::Value& json, OnJsonCb jsoncb,
238 std::shared_ptr<dht::Logger> logger = {});
239 Request(asio::io_context& ctx,
const std::string& url, OnJsonCb jsoncb,
240 std::shared_ptr<dht::Logger> logger = {});
242 Request(asio::io_context& ctx,
const std::string& url, std::shared_ptr<dht::Logger> logger = {});
243 Request(asio::io_context& ctx,
const std::string& host,
const std::string& service,
244 const bool ssl =
false, std::shared_ptr<dht::Logger> logger = {});
245 Request(asio::io_context& ctx,
const std::string& url, OnDoneCb onDone, std::shared_ptr<dht::Logger> logger = {});
248 Request(asio::io_context& ctx, std::shared_ptr<Resolver> resolver, sa_family_t family = AF_UNSPEC);
249 Request(asio::io_context& ctx, std::shared_ptr<Resolver> resolver,
const std::string& target, sa_family_t family = AF_UNSPEC);
252 Request(asio::io_context& ctx, std::vector<asio::ip::tcp::endpoint>&& endpoints,
253 const bool ssl =
false, std::shared_ptr<dht::Logger> logger = {});
257 inline unsigned int id()
const {
return id_; };
258 void set_connection(std::shared_ptr<Connection> connection);
259 std::shared_ptr<Connection> get_connection()
const;
260 inline const Url& get_url()
const {
261 return resolver_->get_url();
269 inline std::string& to_string() {
273 void set_certificate_authority(std::shared_ptr<dht::crypto::Certificate> certificate);
274 void set_identity(
const dht::crypto::Identity& identity);
275 void set_logger(std::shared_ptr<dht::Logger> logger);
281 void set_method(restinio::http_method_id_t method);
282 void set_target(std::string target);
283 void set_header_field(restinio::http_field_t field, std::string value);
284 void set_connection_type(restinio::http_connection_header_t connection);
285 void set_body(std::string body);
286 void set_auth(
const std::string& username,
const std::string& password);
288 void add_on_status_callback(OnStatusCb cb);
289 void add_on_body_callback(OnDataCb cb);
290 void add_on_state_change_callback(OnStateChangeCb cb);
291 void add_on_done_callback(OnDoneCb cb);
302 void terminate(
const asio::error_code& ec);
305 using OnCompleteCb = std::function<void()>;
308 OnStatusCb on_status;
309 OnDataCb on_header_field;
310 OnDataCb on_header_value;
312 OnStateChangeCb on_state_change;
315 static std::string getRelativePath(
const Url& origin,
const std::string& path);
317 void notify_state_change(State state);
321 void init_default_headers();
327 void connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, HandlerCb cb = {});
331 void handle_request(
const asio::error_code& ec);
332 void handle_response(
const asio::error_code& ec,
size_t bytes);
334 void onHeadersComplete();
335 void onBody(
const char* at,
size_t length);
338 mutable std::mutex mutex_;
340 std::shared_ptr<dht::Logger> logger_;
342 restinio::http_request_header_t header_;
343 std::map<restinio::http_field_t, std::string> headers_;
344 restinio::http_connection_header_t connection_type_ {restinio::http_connection_header_t::close};
350 dht::crypto::Identity client_identity_;
351 std::shared_ptr<dht::crypto::Certificate> server_ca_;
352 std::string service_;
356 static std::atomic_uint ids_;
357 asio::io_context& ctx_;
358 sa_family_t family_ = AF_UNSPEC;
359 std::shared_ptr<Connection> conn_;
360 std::shared_ptr<Resolver> resolver_;
362 Response response_ {};
363 std::string request_;
364 std::atomic<bool> finishing_ {
false};
365 std::unique_ptr<http_parser> parser_;
366 std::unique_ptr<http_parser_settings> parser_s_;
369 std::shared_ptr<Request> next_;
370 std::weak_ptr<Request> prev_;
371 unsigned num_redirect {0};
372 bool follow_redirect {
true};
std::shared_ptr< Request > getPrevious() const
void set_header(restinio::http_request_header_t header)