* Start the HTTP request handling. * * This is done in an async manner, so we can do other things while waiting for * the HTTP request to finish. The actual receiving of the data is done in * Receive(). */
| 211 | * Receive(). |
| 212 | */ |
| 213 | void NetworkHTTPRequest::Connect() |
| 214 | { |
| 215 | Debug(net, 1, "HTTP request to {}", std::string(uri.begin(), uri.end())); |
| 216 | |
| 217 | URL_COMPONENTS url_components = {}; |
| 218 | wchar_t scheme[32]; |
| 219 | wchar_t hostname[128]; |
| 220 | wchar_t url_path[4096]; |
| 221 | |
| 222 | /* Convert the URL to its components. */ |
| 223 | url_components.dwStructSize = sizeof(url_components); |
| 224 | url_components.lpszScheme = scheme; |
| 225 | url_components.dwSchemeLength = static_cast<DWORD>(std::size(scheme)); |
| 226 | url_components.lpszHostName = hostname; |
| 227 | url_components.dwHostNameLength = static_cast<DWORD>(std::size(hostname)); |
| 228 | url_components.lpszUrlPath = url_path; |
| 229 | url_components.dwUrlPathLength = static_cast<DWORD>(std::size(url_path)); |
| 230 | WinHttpCrackUrl(this->uri.c_str(), 0, 0, &url_components); |
| 231 | |
| 232 | /* Create the HTTP connection. */ |
| 233 | this->connection = WinHttpConnect(_winhttp_session, url_components.lpszHostName, url_components.nPort, 0); |
| 234 | if (this->connection == nullptr) { |
| 235 | Debug(net, 0, "HTTP request failed: {}", GetLastErrorAsString()); |
| 236 | this->callback.OnFailure(); |
| 237 | this->finished = true; |
| 238 | return; |
| 239 | } |
| 240 | |
| 241 | this->request = WinHttpOpenRequest(connection, data.empty() ? L"GET" : L"POST", url_components.lpszUrlPath, nullptr, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, url_components.nScheme == INTERNET_SCHEME_HTTPS ? WINHTTP_FLAG_SECURE : 0); |
| 242 | if (this->request == nullptr) { |
| 243 | WinHttpCloseHandle(this->connection); |
| 244 | |
| 245 | Debug(net, 0, "HTTP request failed: {}", GetLastErrorAsString()); |
| 246 | this->callback.OnFailure(); |
| 247 | this->finished = true; |
| 248 | return; |
| 249 | } |
| 250 | |
| 251 | /* Send the request (possibly with a payload). */ |
| 252 | if (data.empty()) { |
| 253 | WinHttpSendRequest(this->request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, reinterpret_cast<DWORD_PTR>(this)); |
| 254 | } else { |
| 255 | /* When the payload starts with a '{', it is a JSON payload. */ |
| 256 | LPCWSTR content_type = data.starts_with("{") ? L"Content-Type: application/json\r\n" : L"Content-Type: application/x-www-form-urlencoded\r\n"; |
| 257 | WinHttpSendRequest(this->request, content_type, -1, const_cast<char *>(data.data()), static_cast<DWORD>(data.size()), static_cast<DWORD>(data.size()), reinterpret_cast<DWORD_PTR>(this)); |
| 258 | } |
| 259 | } |
| 260 | |
| 261 | /** |
| 262 | * Poll and process the HTTP request/response. |
nothing calls this directly
no test coverage detected