https_execute.hpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  1. /*
  2. * Copyright (c) 2017-2023 zhllxt
  3. *
  4. * author : zhllxt
  5. * email : 37792738@qq.com
  6. *
  7. * Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. */
  10. #if defined(ASIO2_ENABLE_SSL) || defined(ASIO2_USE_SSL)
  11. #ifndef __ASIO2_HTTPS_EXECUTE_HPP__
  12. #define __ASIO2_HTTPS_EXECUTE_HPP__
  13. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  14. #pragma once
  15. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  16. #include <asio2/base/detail/push_options.hpp>
  17. #include <asio2/base/detail/function_traits.hpp>
  18. #include <asio2/util/string.hpp>
  19. #include <asio2/http/detail/http_util.hpp>
  20. #include <asio2/http/detail/http_make.hpp>
  21. #include <asio2/http/detail/http_traits.hpp>
  22. #include <asio2/component/socks/socks5_client_cp.hpp>
  23. namespace asio2::detail
  24. {
  25. template<class derived_t, class args_t, bool Enable = is_https_execute_download_enabled<args_t>::value()>
  26. struct https_execute_impl_bridge;
  27. template<class derived_t, class args_t>
  28. struct https_execute_impl_bridge<derived_t, args_t, false>
  29. {
  30. };
  31. template<class derived_t, class args_t>
  32. struct https_execute_impl_bridge<derived_t, args_t, true>
  33. {
  34. protected:
  35. template<typename String, typename StrOrInt, class Proxy, class Body, class Fields, class Buffer>
  36. static void _execute_with_socks5(
  37. asio::io_context& ioc, asio::ip::tcp::resolver& resolver, asio::ip::tcp::socket& socket,
  38. asio::ssl::stream<asio::ip::tcp::socket&>& stream,
  39. http::parser<false, Body, typename Fields::allocator_type>& parser,
  40. Buffer& buffer,
  41. String&& host, StrOrInt&& port,
  42. http::request<Body, Fields>& req, Proxy&& proxy)
  43. {
  44. auto sk5 = detail::to_shared_ptr(std::forward<Proxy>(proxy));
  45. std::string_view h{ sk5->host() };
  46. std::string_view p{ sk5->port() };
  47. if (static_cast<int>(sk5->command()) == 0)
  48. {
  49. sk5->command(socks5::command::connect);
  50. }
  51. // Look up the domain name
  52. resolver.async_resolve(h, p, [&, s5 = std::move(sk5)]
  53. (const error_code& ec1, const asio::ip::tcp::resolver::results_type& endpoints) mutable
  54. {
  55. if (ec1) { set_last_error(ec1); return; }
  56. // Make the connection on the IP address we get from a lookup
  57. asio::async_connect(socket, endpoints,
  58. [&, s5 = std::move(s5)](const error_code& ec2, const asio::ip::tcp::endpoint&) mutable
  59. {
  60. if (ec2) { set_last_error(ec2); return; }
  61. socks5_async_handshake
  62. (
  63. detail::to_string(std::forward<String >(host)),
  64. detail::to_string(std::forward<StrOrInt>(port)),
  65. socket,
  66. std::move(s5),
  67. [&](error_code ecs5, std::string, std::string) mutable
  68. {
  69. if (ecs5) { set_last_error(ecs5); return; }
  70. // https://github.com/djarek/certify
  71. if (auto it = req.find(http::field::host); it != req.end())
  72. {
  73. std::string hostname(it->value());
  74. SSL_set_tlsext_host_name(stream.native_handle(), hostname.data());
  75. }
  76. stream.async_handshake(asio::ssl::stream_base::client,
  77. [&](const error_code& ec3) mutable
  78. {
  79. if (ec3) { set_last_error(ec3); return; }
  80. http::async_write(stream, req, [&](const error_code& ec4, std::size_t) mutable
  81. {
  82. // can't use stream.shutdown(),in some case the shutdowm will blocking forever.
  83. if (ec4) { set_last_error(ec4); stream.async_shutdown([](const error_code&) {}); return; }
  84. // Then start asynchronous reading
  85. http::async_read(stream, buffer, parser,
  86. [&](const error_code& ec5, std::size_t) mutable
  87. {
  88. // Reading completed, assign the read the result to last error
  89. // If the code does not execute into here, the last error
  90. // is the default value timed_out.
  91. set_last_error(ec5);
  92. stream.async_shutdown([](const error_code&) mutable {});
  93. });
  94. });
  95. });
  96. }
  97. );
  98. });
  99. });
  100. }
  101. template<typename String, typename StrOrInt, class Body, class Fields, class Buffer>
  102. static void _execute_trivially(
  103. asio::io_context& ioc, asio::ip::tcp::resolver& resolver, asio::ip::tcp::socket& socket,
  104. asio::ssl::stream<asio::ip::tcp::socket&>& stream,
  105. http::parser<false, Body, typename Fields::allocator_type>& parser,
  106. Buffer& buffer,
  107. String&& host, StrOrInt&& port,
  108. http::request<Body, Fields>& req)
  109. {
  110. detail::ignore_unused(ioc);
  111. // Look up the domain name
  112. resolver.async_resolve(std::forward<String>(host), detail::to_string(std::forward<StrOrInt>(port)),
  113. [&](const error_code& ec1, const asio::ip::tcp::resolver::results_type& endpoints) mutable
  114. {
  115. if (ec1) { set_last_error(ec1); return; }
  116. // Make the connection on the IP address we get from a lookup
  117. asio::async_connect(socket, endpoints,
  118. [&](const error_code& ec2, const asio::ip::tcp::endpoint&) mutable
  119. {
  120. if (ec2) { set_last_error(ec2); return; }
  121. // https://github.com/djarek/certify
  122. if (auto it = req.find(http::field::host); it != req.end())
  123. {
  124. std::string hostname(it->value());
  125. SSL_set_tlsext_host_name(stream.native_handle(), hostname.data());
  126. }
  127. stream.async_handshake(asio::ssl::stream_base::client,
  128. [&](const error_code& ec3) mutable
  129. {
  130. if (ec3) { set_last_error(ec3); return; }
  131. http::async_write(stream, req, [&](const error_code& ec4, std::size_t) mutable
  132. {
  133. // can't use stream.shutdown(),in some case the shutdowm will blocking forever.
  134. if (ec4) { set_last_error(ec4); stream.async_shutdown([](const error_code&) {}); return; }
  135. // Then start asynchronous reading
  136. http::async_read(stream, buffer, parser,
  137. [&](const error_code& ec5, std::size_t) mutable
  138. {
  139. // Reading completed, assign the read the result to last error
  140. // If the code does not execute into here, the last error
  141. // is the default value timed_out.
  142. set_last_error(ec5);
  143. stream.async_shutdown([](const error_code&) mutable {});
  144. });
  145. });
  146. });
  147. });
  148. });
  149. }
  150. template<typename String, typename StrOrInt, class Proxy, class Body, class Fields, class Buffer>
  151. static void _execute_impl(
  152. asio::io_context& ioc, asio::ip::tcp::resolver& resolver, asio::ip::tcp::socket& socket,
  153. asio::ssl::stream<asio::ip::tcp::socket&>& stream,
  154. http::parser<false, Body, typename Fields::allocator_type>& parser,
  155. Buffer& buffer,
  156. String&& host, StrOrInt&& port,
  157. http::request<Body, Fields>& req, Proxy&& proxy)
  158. {
  159. // if has socks5 proxy
  160. if constexpr (std::is_base_of_v<asio2::socks5::option_base,
  161. typename detail::element_type_adapter<detail::remove_cvref_t<Proxy>>::type>)
  162. {
  163. derived_t::_execute_with_socks5(ioc, resolver, socket, stream, parser, buffer
  164. , std::forward<String>(host), std::forward<StrOrInt>(port)
  165. , req
  166. , std::forward<Proxy>(proxy)
  167. );
  168. }
  169. else
  170. {
  171. detail::ignore_unused(proxy);
  172. derived_t::_execute_trivially(ioc, resolver, socket, stream, parser, buffer
  173. , std::forward<String>(host), std::forward<StrOrInt>(port)
  174. , req
  175. );
  176. }
  177. }
  178. public:
  179. template<typename String, typename StrOrInt, class Rep, class Period, class Proxy,
  180. class Body = http::string_body, class Fields = http::fields, class Buffer = beast::flat_buffer>
  181. typename std::enable_if_t<detail::is_character_string_v<detail::remove_cvref_t<String>>
  182. && detail::http_proxy_checker_v<Proxy>, http::response<Body, Fields>>
  183. static inline execute(const asio::ssl::context& ctx, String&& host, StrOrInt&& port,
  184. http::request<Body, Fields>& req, std::chrono::duration<Rep, Period> timeout, Proxy&& proxy)
  185. {
  186. http::parser<false, Body, typename Fields::allocator_type> parser;
  187. // First assign default value timed_out to last error
  188. set_last_error(asio::error::timed_out);
  189. // set default result to unknown
  190. parser.get().result(http::status::unknown);
  191. parser.eager(true);
  192. // The io_context is required for all I/O
  193. asio::io_context ioc;
  194. // These objects perform our I/O
  195. asio::ip::tcp::resolver resolver{ ioc };
  196. asio::ip::tcp::socket socket{ ioc };
  197. asio::ssl::stream<asio::ip::tcp::socket&> stream(socket, const_cast<asio::ssl::context&>(ctx));
  198. // This buffer is used for reading and must be persisted
  199. Buffer buffer;
  200. // Some sites must set the http::field::host
  201. if (req.find(http::field::host) == req.end())
  202. {
  203. std::string strhost = asio2::to_string(host);
  204. std::string strport = asio2::to_string(port);
  205. if (strport != "443")
  206. {
  207. strhost += ":";
  208. strhost += strport;
  209. }
  210. req.set(http::field::host, strhost);
  211. }
  212. // Some sites must set the http::field::user_agent
  213. if (req.find(http::field::user_agent) == req.end())
  214. {
  215. req.set(http::field::user_agent,
  216. "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36");
  217. }
  218. // do work
  219. derived_t::_execute_impl(ioc, resolver, socket, stream, parser, buffer
  220. , std::forward<String>(host), std::forward<StrOrInt>(port)
  221. , req
  222. , std::forward<Proxy>(proxy)
  223. );
  224. // timedout run
  225. ioc.run_for(timeout);
  226. error_code ec_ignore{};
  227. // Gracefully close the socket
  228. socket.shutdown(asio::ip::tcp::socket::shutdown_both, ec_ignore);
  229. socket.cancel(ec_ignore);
  230. socket.close(ec_ignore);
  231. return parser.release();
  232. }
  233. // ----------------------------------------------------------------------------------------
  234. template<typename String, typename StrOrInt, class Rep, class Period,
  235. class Body = http::string_body, class Fields = http::fields>
  236. typename std::enable_if_t<detail::is_character_string_v<detail::remove_cvref_t<String>>
  237. , http::response<Body, Fields>>
  238. static inline execute(
  239. const asio::ssl::context& ctx, String&& host, StrOrInt&& port,
  240. http::request<Body, Fields>& req, std::chrono::duration<Rep, Period> timeout)
  241. {
  242. return derived_t::execute(ctx, std::forward<String>(host), std::forward<StrOrInt>(port),
  243. req, timeout, std::in_place);
  244. }
  245. template<typename String, typename StrOrInt,
  246. class Body = http::string_body, class Fields = http::fields>
  247. typename std::enable_if_t<detail::is_character_string_v<detail::remove_cvref_t<String>>
  248. , http::response<Body, Fields>>
  249. static inline execute(
  250. const asio::ssl::context& ctx, String&& host, StrOrInt&& port,
  251. http::request<Body, Fields>& req)
  252. {
  253. return derived_t::execute(ctx, std::forward<String>(host), std::forward<StrOrInt>(port),
  254. req, std::chrono::milliseconds(http_execute_timeout), std::in_place);
  255. }
  256. // ----------------------------------------------------------------------------------------
  257. template<typename String, typename StrOrInt, class Rep, class Period,
  258. class Body = http::string_body, class Fields = http::fields>
  259. typename std::enable_if_t<detail::is_character_string_v<detail::remove_cvref_t<String>>
  260. , http::response<Body, Fields>>
  261. static inline execute(String&& host, StrOrInt&& port,
  262. http::request<Body, Fields>& req, std::chrono::duration<Rep, Period> timeout)
  263. {
  264. return derived_t::execute(asio::ssl::context{ ASIO2_DEFAULT_SSL_METHOD },
  265. std::forward<String>(host), std::forward<StrOrInt>(port), req, timeout, std::in_place);
  266. }
  267. template<typename String, typename StrOrInt, class Body = http::string_body, class Fields = http::fields>
  268. typename std::enable_if_t<detail::is_character_string_v<detail::remove_cvref_t<String>>
  269. , http::response<Body, Fields>>
  270. static inline execute(String&& host, StrOrInt&& port, http::request<Body, Fields>& req)
  271. {
  272. return derived_t::execute(
  273. std::forward<String>(host), std::forward<StrOrInt>(port),
  274. req, std::chrono::milliseconds(http_execute_timeout));
  275. }
  276. // ----------------------------------------------------------------------------------------
  277. template<class Rep, class Period, class Body = http::string_body, class Fields = http::fields>
  278. static inline http::response<Body, Fields> execute(
  279. const asio::ssl::context& ctx, http::web_request& req, std::chrono::duration<Rep, Period> timeout)
  280. {
  281. return derived_t::execute(ctx, req.url().host(), req.url().port(), req.base(), timeout, std::in_place);
  282. }
  283. template<class Body = http::string_body, class Fields = http::fields>
  284. static inline http::response<Body, Fields> execute(
  285. const asio::ssl::context& ctx, http::web_request& req)
  286. {
  287. return derived_t::execute(ctx, req, std::chrono::milliseconds(http_execute_timeout));
  288. }
  289. template<class Rep, class Period, class Body = http::string_body, class Fields = http::fields>
  290. static inline http::response<Body, Fields> execute(
  291. http::web_request& req, std::chrono::duration<Rep, Period> timeout)
  292. {
  293. return derived_t::execute(asio::ssl::context{ ASIO2_DEFAULT_SSL_METHOD }, req, timeout);
  294. }
  295. template<class Body = http::string_body, class Fields = http::fields>
  296. static inline http::response<Body, Fields> execute(http::web_request& req)
  297. {
  298. return derived_t::execute(req, std::chrono::milliseconds(http_execute_timeout));
  299. }
  300. // ----------------------------------------------------------------------------------------
  301. /**
  302. * @brief blocking execute the http request until it is returned on success or failure
  303. */
  304. template<class Rep, class Period, class Body = http::string_body, class Fields = http::fields>
  305. static inline http::response<Body, Fields> execute(const asio::ssl::context& ctx, std::string_view url,
  306. std::chrono::duration<Rep, Period> timeout)
  307. {
  308. http::web_request req = http::make_request(url);
  309. if (get_last_error())
  310. {
  311. return http::response<Body, Fields>{ http::status::unknown, 11};
  312. }
  313. return derived_t::execute(ctx, req.host(), req.port(), req.base(), timeout, std::in_place);
  314. }
  315. /**
  316. * @brief blocking execute the http request until it is returned on success or failure
  317. */
  318. template<class Body = http::string_body, class Fields = http::fields>
  319. static inline http::response<Body, Fields> execute(const asio::ssl::context& ctx, std::string_view url)
  320. {
  321. return derived_t::execute(ctx, url, std::chrono::milliseconds(http_execute_timeout));
  322. }
  323. // ----------------------------------------------------------------------------------------
  324. /**
  325. * @brief blocking execute the http request until it is returned on success or failure
  326. */
  327. template<class Rep, class Period, class Body = http::string_body, class Fields = http::fields>
  328. static inline http::response<Body, Fields> execute(std::string_view url,
  329. std::chrono::duration<Rep, Period> timeout)
  330. {
  331. return derived_t::execute(asio::ssl::context{ ASIO2_DEFAULT_SSL_METHOD }, url, timeout);
  332. }
  333. /**
  334. * @brief blocking execute the http request until it is returned on success or failure
  335. */
  336. template<class Body = http::string_body, class Fields = http::fields>
  337. static inline http::response<Body, Fields> execute(std::string_view url)
  338. {
  339. return derived_t::execute(url, std::chrono::milliseconds(http_execute_timeout));
  340. }
  341. // ----------------------------------------------------------------------------------------
  342. /**
  343. * @brief blocking execute the http request until it is returned on success or failure
  344. */
  345. template<typename String, typename StrOrInt, class Rep, class Period,
  346. class Body = http::string_body, class Fields = http::fields>
  347. typename std::enable_if_t<detail::is_character_string_v<detail::remove_cvref_t<String>>
  348. , http::response<Body, Fields>>
  349. static inline execute(
  350. const asio::ssl::context& ctx, String&& host, StrOrInt&& port,
  351. std::string_view target, std::chrono::duration<Rep, Period> timeout)
  352. {
  353. http::web_request req = http::make_request(host, port, target);
  354. if (get_last_error())
  355. {
  356. return http::response<Body, Fields>{ http::status::unknown, 11};
  357. }
  358. return derived_t::execute(ctx,
  359. std::forward<String>(host), std::forward<StrOrInt>(port),
  360. req.base(), timeout, std::in_place);
  361. }
  362. /**
  363. * @brief blocking execute the http request until it is returned on success or failure
  364. */
  365. template<typename String, typename StrOrInt, class Body = http::string_body, class Fields = http::fields>
  366. typename std::enable_if_t<detail::is_character_string_v<detail::remove_cvref_t<String>>
  367. , http::response<Body, Fields>>
  368. static inline execute(
  369. const asio::ssl::context& ctx, String&& host, StrOrInt&& port,
  370. std::string_view target)
  371. {
  372. return derived_t::execute(ctx,
  373. std::forward<String>(host), std::forward<StrOrInt>(port),
  374. target, std::chrono::milliseconds(http_execute_timeout));
  375. }
  376. // ----------------------------------------------------------------------------------------
  377. /**
  378. * @brief blocking execute the http request until it is returned on success or failure
  379. */
  380. template<typename String, typename StrOrInt, class Rep, class Period,
  381. class Body = http::string_body, class Fields = http::fields>
  382. typename std::enable_if_t<detail::can_convert_to_string_v<detail::remove_cvref_t<String>>,
  383. http::response<Body, Fields>>
  384. static inline execute(String&& host, StrOrInt&& port, std::string_view target,
  385. std::chrono::duration<Rep, Period> timeout)
  386. {
  387. return derived_t::execute(asio::ssl::context{ ASIO2_DEFAULT_SSL_METHOD },
  388. std::forward<String>(host), std::forward<StrOrInt>(port),
  389. target, timeout);
  390. }
  391. /**
  392. * @brief blocking execute the http request until it is returned on success or failure
  393. */
  394. template<typename String, typename StrOrInt, class Body = http::string_body, class Fields = http::fields>
  395. typename std::enable_if_t<detail::can_convert_to_string_v<detail::remove_cvref_t<String>>,
  396. http::response<Body, Fields>>
  397. static inline execute(String&& host, StrOrInt&& port, std::string_view target)
  398. {
  399. return derived_t::execute(
  400. std::forward<String>(host), std::forward<StrOrInt>(port),
  401. target, std::chrono::milliseconds(http_execute_timeout));
  402. }
  403. // ----------------------------------------------------------------------------------------
  404. template<typename String, typename StrOrInt, class Proxy,
  405. class Body = http::string_body, class Fields = http::fields>
  406. typename std::enable_if_t<detail::is_character_string_v<detail::remove_cvref_t<String>>
  407. && detail::http_proxy_checker_v<Proxy>, http::response<Body, Fields>>
  408. static inline execute(
  409. const asio::ssl::context& ctx, String&& host, StrOrInt&& port,
  410. http::request<Body, Fields>& req, Proxy&& proxy)
  411. {
  412. return derived_t::execute(ctx, std::forward<String>(host), std::forward<StrOrInt>(port),
  413. req, std::chrono::milliseconds(http_execute_timeout), std::forward<Proxy>(proxy));
  414. }
  415. // ----------------------------------------------------------------------------------------
  416. template<typename String, typename StrOrInt, class Proxy, class Rep, class Period,
  417. class Body = http::string_body, class Fields = http::fields>
  418. typename std::enable_if_t<detail::is_character_string_v<detail::remove_cvref_t<String>>
  419. && detail::http_proxy_checker_v<Proxy>, http::response<Body, Fields>>
  420. static inline execute(String&& host, StrOrInt&& port,
  421. http::request<Body, Fields>& req, std::chrono::duration<Rep, Period> timeout, Proxy&& proxy)
  422. {
  423. return derived_t::execute(asio::ssl::context{ ASIO2_DEFAULT_SSL_METHOD },
  424. std::forward<String>(host), std::forward<StrOrInt>(port),
  425. req, timeout, std::forward<Proxy>(proxy));
  426. }
  427. template<typename String, typename StrOrInt, class Proxy,
  428. class Body = http::string_body, class Fields = http::fields>
  429. typename std::enable_if_t<detail::is_character_string_v<detail::remove_cvref_t<String>>
  430. && detail::http_proxy_checker_v<Proxy>, http::response<Body, Fields>>
  431. static inline execute(String&& host, StrOrInt&& port, http::request<Body, Fields>& req, Proxy&& proxy)
  432. {
  433. return derived_t::execute(
  434. std::forward<String>(host), std::forward<StrOrInt>(port),
  435. req, std::chrono::milliseconds(http_execute_timeout), std::forward<Proxy>(proxy));
  436. }
  437. // ----------------------------------------------------------------------------------------
  438. template<class Proxy, class Rep, class Period,
  439. class Body = http::string_body, class Fields = http::fields>
  440. typename std::enable_if_t<detail::http_proxy_checker_v<Proxy>, http::response<Body, Fields>>
  441. static inline execute(
  442. const asio::ssl::context& ctx, http::web_request& req,
  443. std::chrono::duration<Rep, Period> timeout, Proxy&& proxy)
  444. {
  445. return derived_t::execute(ctx, req.url().host(), req.url().port(), req.base(), timeout,
  446. std::forward<Proxy>(proxy));
  447. }
  448. template<class Proxy, class Body = http::string_body, class Fields = http::fields>
  449. typename std::enable_if_t<detail::http_proxy_checker_v<Proxy>, http::response<Body, Fields>>
  450. static inline execute(const asio::ssl::context& ctx, http::web_request& req, Proxy&& proxy)
  451. {
  452. return derived_t::execute(ctx, req, std::chrono::milliseconds(http_execute_timeout),
  453. std::forward<Proxy>(proxy));
  454. }
  455. template<class Proxy, class Rep, class Period,
  456. class Body = http::string_body, class Fields = http::fields>
  457. typename std::enable_if_t<detail::http_proxy_checker_v<Proxy>, http::response<Body, Fields>>
  458. static inline execute(
  459. http::web_request& req, std::chrono::duration<Rep, Period> timeout, Proxy&& proxy)
  460. {
  461. return derived_t::execute(asio::ssl::context{ ASIO2_DEFAULT_SSL_METHOD }, req, timeout,
  462. std::forward<Proxy>(proxy));
  463. }
  464. template<class Proxy, class Body = http::string_body, class Fields = http::fields>
  465. typename std::enable_if_t<detail::http_proxy_checker_v<Proxy>, http::response<Body, Fields>>
  466. static inline execute(http::web_request& req, Proxy&& proxy)
  467. {
  468. return derived_t::execute(req, std::chrono::milliseconds(http_execute_timeout),
  469. std::forward<Proxy>(proxy));
  470. }
  471. // ----------------------------------------------------------------------------------------
  472. /**
  473. * @brief blocking execute the http request until it is returned on success or failure
  474. */
  475. template<class Proxy, class Rep, class Period,
  476. class Body = http::string_body, class Fields = http::fields>
  477. typename std::enable_if_t<detail::http_proxy_checker_v<Proxy>, http::response<Body, Fields>>
  478. static inline execute(
  479. const asio::ssl::context& ctx, std::string_view url,
  480. std::chrono::duration<Rep, Period> timeout, Proxy&& proxy)
  481. {
  482. http::web_request req = http::make_request(url);
  483. if (get_last_error())
  484. {
  485. return http::response<Body, Fields>{ http::status::unknown, 11};
  486. }
  487. return derived_t::execute(ctx, req.host(), req.port(), req.base(), timeout, std::forward<Proxy>(proxy));
  488. }
  489. /**
  490. * @brief blocking execute the http request until it is returned on success or failure
  491. */
  492. template<class Proxy, class Body = http::string_body, class Fields = http::fields>
  493. typename std::enable_if_t<detail::http_proxy_checker_v<Proxy>, http::response<Body, Fields>>
  494. static inline execute(const asio::ssl::context& ctx, std::string_view url, Proxy&& proxy)
  495. {
  496. return derived_t::execute(ctx, url, std::chrono::milliseconds(http_execute_timeout),
  497. std::forward<Proxy>(proxy));
  498. }
  499. // ----------------------------------------------------------------------------------------
  500. /**
  501. * @brief blocking execute the http request until it is returned on success or failure
  502. */
  503. template<class Proxy, class Rep, class Period,
  504. class Body = http::string_body, class Fields = http::fields>
  505. typename std::enable_if_t<detail::http_proxy_checker_v<Proxy>, http::response<Body, Fields>>
  506. static inline execute(std::string_view url, std::chrono::duration<Rep, Period> timeout, Proxy&& proxy)
  507. {
  508. return derived_t::execute(asio::ssl::context{ ASIO2_DEFAULT_SSL_METHOD }, url, timeout,
  509. std::forward<Proxy>(proxy));
  510. }
  511. /**
  512. * @brief blocking execute the http request until it is returned on success or failure
  513. */
  514. template<class Proxy, class Body = http::string_body, class Fields = http::fields>
  515. typename std::enable_if_t<detail::http_proxy_checker_v<Proxy>, http::response<Body, Fields>>
  516. static inline execute(std::string_view url, Proxy&& proxy)
  517. {
  518. return derived_t::execute(url, std::chrono::milliseconds(http_execute_timeout),
  519. std::forward<Proxy>(proxy));
  520. }
  521. // ----------------------------------------------------------------------------------------
  522. /**
  523. * @brief blocking execute the http request until it is returned on success or failure
  524. */
  525. template<typename String, typename StrOrInt, class Proxy, class Rep, class Period,
  526. class Body = http::string_body, class Fields = http::fields>
  527. typename std::enable_if_t<detail::is_character_string_v<detail::remove_cvref_t<String>>
  528. && detail::http_proxy_checker_v<Proxy>, http::response<Body, Fields>>
  529. static inline execute(
  530. const asio::ssl::context& ctx, String&& host, StrOrInt&& port,
  531. std::string_view target, std::chrono::duration<Rep, Period> timeout, Proxy&& proxy)
  532. {
  533. http::web_request req = http::make_request(host, port, target);
  534. if (get_last_error())
  535. {
  536. return http::response<Body, Fields>{ http::status::unknown, 11};
  537. }
  538. return derived_t::execute(ctx,
  539. std::forward<String>(host), std::forward<StrOrInt>(port),
  540. req.base(), timeout, std::forward<Proxy>(proxy));
  541. }
  542. /**
  543. * @brief blocking execute the http request until it is returned on success or failure
  544. */
  545. template<typename String, typename StrOrInt, class Proxy,
  546. class Body = http::string_body, class Fields = http::fields>
  547. typename std::enable_if_t<detail::is_character_string_v<detail::remove_cvref_t<String>>
  548. && detail::http_proxy_checker_v<Proxy>, http::response<Body, Fields>>
  549. static inline execute(
  550. const asio::ssl::context& ctx, String&& host, StrOrInt&& port,
  551. std::string_view target, Proxy&& proxy)
  552. {
  553. return derived_t::execute(ctx,
  554. std::forward<String>(host), std::forward<StrOrInt>(port),
  555. target, std::chrono::milliseconds(http_execute_timeout), std::forward<Proxy>(proxy));
  556. }
  557. // ----------------------------------------------------------------------------------------
  558. /**
  559. * @brief blocking execute the http request until it is returned on success or failure
  560. */
  561. template<typename String, typename StrOrInt, class Proxy, class Rep, class Period,
  562. class Body = http::string_body, class Fields = http::fields>
  563. typename std::enable_if_t<detail::is_character_string_v<detail::remove_cvref_t<String>>
  564. && detail::http_proxy_checker_v<Proxy>, http::response<Body, Fields>>
  565. static inline execute(String&& host, StrOrInt&& port, std::string_view target,
  566. std::chrono::duration<Rep, Period> timeout, Proxy&& proxy)
  567. {
  568. return derived_t::execute(asio::ssl::context{ ASIO2_DEFAULT_SSL_METHOD },
  569. std::forward<String>(host), std::forward<StrOrInt>(port),
  570. target, timeout, std::forward<Proxy>(proxy));
  571. }
  572. /**
  573. * @brief blocking execute the http request until it is returned on success or failure
  574. */
  575. template<typename String, typename StrOrInt, class Proxy,
  576. class Body = http::string_body, class Fields = http::fields>
  577. typename std::enable_if_t<detail::is_character_string_v<detail::remove_cvref_t<String>>
  578. && detail::http_proxy_checker_v<Proxy>, http::response<Body, Fields>>
  579. static inline execute(String&& host, StrOrInt&& port, std::string_view target, Proxy&& proxy)
  580. {
  581. return derived_t::execute(
  582. std::forward<String>(host), std::forward<StrOrInt>(port),
  583. target, std::chrono::milliseconds(http_execute_timeout), std::forward<Proxy>(proxy));
  584. }
  585. };
  586. template<class derived_t, class args_t = void>
  587. struct https_execute_impl : public https_execute_impl_bridge<derived_t, args_t> {};
  588. }
  589. #include <asio2/base/detail/pop_options.hpp>
  590. #endif // !__ASIO2_HTTPS_EXECUTE_HPP__
  591. #endif