std::shared_ptr<Aws::Http::HttpResponse> NetlibHttpClient::MakeRequest( Aws::Http::HttpRequest& request, Aws::Utils::RateLimits::RateLimiterInterface* readLimiter, Aws::Utils::RateLimits::RateLimiterInterface* writeLimiter) const { // AWS allows rate limiters to be passed around, but we are doing rate // limiting on the logger plugin side and so don't implement this. if (readLimiter != nullptr || writeLimiter != nullptr) { LOG(WARNING) << "Read/write limiters are unsupported"; } Aws::Http::URI uri = request.GetUri(); uri.SetPath(Aws::Http::URI::URLEncodePath(uri.GetPath())); Aws::String url = uri.GetURIString(); bn::http::client client = TLSTransport().getClient(); bn::http::client::request req(url); for (const auto& requestHeader : request.GetHeaders()) { req << bn::header(requestHeader.first, requestHeader.second); } std::string body; if (request.GetContentBody()) { std::stringstream ss; ss << request.GetContentBody()->rdbuf(); body = ss.str(); } auto response = std::make_shared<Standard::StandardHttpResponse>(request); try { bn::http::client::response resp; switch (request.GetMethod()) { case Aws::Http::HttpMethod::HTTP_GET: resp = client.get(req); if (resp.status() == 301 || resp.status() == 302) { VLOG(1) << "Attempting custom redirect as cpp-netlib does not support " "redirects"; for (const auto& header : resp.headers()) { if (header.first == "Location") { req.uri(header.second); resp = client.get(req); } } } break; case Aws::Http::HttpMethod::HTTP_POST: resp = client.post(req, body, request.GetContentType()); break; case Aws::Http::HttpMethod::HTTP_PUT: resp = client.put(req, body, request.GetContentType()); break; case Aws::Http::HttpMethod::HTTP_HEAD: resp = client.head(req); break; case Aws::Http::HttpMethod::HTTP_PATCH: LOG(ERROR) << "cpp-netlib does not support HTTP PATCH"; return nullptr; break; case Aws::Http::HttpMethod::HTTP_DELETE: resp = client.delete_(req); break; default: LOG(ERROR) << "Unrecognized HTTP Method used: " << static_cast<int>(request.GetMethod()); return nullptr; break; } response->SetResponseCode( static_cast<Aws::Http::HttpResponseCode>(resp.status())); for (const auto& header : resp.headers()) { if (header.first == "content-type") { response->SetContentType(header.second); } response->AddHeader(header.first, header.second); } response->GetResponseBody() << resp.body(); } catch (const std::exception& /*e*/) { LOG(ERROR) << "Exception making HTTP request to URL: " << url; return nullptr; } return response; }
std::shared_ptr<HttpResponse> WinSyncHttpClient::BuildSuccessResponse(const Aws::Http::HttpRequest& request, void* hHttpRequest, Aws::Utils::RateLimits::RateLimiterInterface* readLimiter) const { auto response = Aws::MakeShared<StandardHttpResponse>(GetLogTag(), request); Aws::StringStream ss; uint64_t read = 0; DoQueryHeaders(hHttpRequest, response, ss, read); if(readLimiter != nullptr && read > 0) { readLimiter->ApplyAndPayForCost(read); } Aws::Vector<Aws::String> rawHeaders = StringUtils::SplitOnLine(ss.str()); for (auto& header : rawHeaders) { Aws::Vector<Aws::String> keyValuePair = StringUtils::Split(header, ':'); if (keyValuePair.size() > 1) { Aws::String headerName = keyValuePair[0]; headerName = StringUtils::Trim(headerName.c_str()); Aws::String headerValue(keyValuePair[1]); for (unsigned i = 2; i < keyValuePair.size(); ++i) { headerValue += ":"; headerValue += keyValuePair[i]; } response->AddHeader(headerName, StringUtils::Trim(headerValue.c_str())); } } if (request.GetMethod() != HttpMethod::HTTP_HEAD) { char body[1024]; uint64_t bodySize = sizeof(body); read = 0; bool success = true; while (DoReadData(hHttpRequest, body, bodySize, read) && read > 0 && success) { response->GetResponseBody().write(body, read); if (read > 0) { if (readLimiter != nullptr) { readLimiter->ApplyAndPayForCost(read); } auto& receivedHandler = request.GetDataReceivedEventHandler(); if (receivedHandler) { receivedHandler(&request, response.get(), (long long)read); } } success = success && IsRequestProcessingEnabled(); } if(!success) { return nullptr; } } //go ahead and flush the response body. response->GetResponseBody().flush(); return response; }