| 61 | } |
| 62 | |
| 63 | std::future<HTTPResponse> HTTPSClientEx::SendRequest(const HTTPRequest& request, const CppCommon::Timespan& timeout) |
| 64 | { |
| 65 | // Create TCP resolver if the current one is empty |
| 66 | if (!_resolver) |
| 67 | _resolver = std::make_shared<Asio::TCPResolver>(service()); |
| 68 | // Create timeout check timer if the current one is empty |
| 69 | if (!_timeout) |
| 70 | _timeout = std::make_shared<Asio::Timer>(service()); |
| 71 | |
| 72 | _promise = std::promise<HTTPResponse>(); |
| 73 | _request = request; |
| 74 | |
| 75 | // Check if the HTTP request is valid |
| 76 | if (_request.empty() || _request.error()) |
| 77 | { |
| 78 | SetPromiseError("Invalid HTTP request!"); |
| 79 | return _promise.get_future(); |
| 80 | } |
| 81 | |
| 82 | if (!IsHandshaked()) |
| 83 | { |
| 84 | // Connect to the Web server |
| 85 | if (!ConnectAsync(_resolver)) |
| 86 | { |
| 87 | SetPromiseError("Connection failed!"); |
| 88 | return _promise.get_future(); |
| 89 | } |
| 90 | } |
| 91 | else |
| 92 | { |
| 93 | // Send prepared HTTP request |
| 94 | if (!SendRequestAsync()) |
| 95 | { |
| 96 | SetPromiseError("Failed to send HTTP request!"); |
| 97 | return _promise.get_future(); |
| 98 | } |
| 99 | } |
| 100 | |
| 101 | // Setup timeout check timer |
| 102 | auto self(this->shared_from_this()); |
| 103 | auto timeout_handler = [this, self](bool canceled) |
| 104 | { |
| 105 | if (canceled) |
| 106 | return; |
| 107 | |
| 108 | // Disconnect on timeout |
| 109 | onReceivedResponseError(_response, "Timeout!"); |
| 110 | _response.Clear(); |
| 111 | DisconnectAsync(); |
| 112 | }; |
| 113 | if (!_timeout->Setup(timeout_handler, timeout) || !_timeout->WaitAsync()) |
| 114 | { |
| 115 | SetPromiseError("Failed to setup timeout timer!"); |
| 116 | return _promise.get_future(); |
| 117 | } |
| 118 | |
| 119 | return _promise.get_future(); |
| 120 | } |