timeout support when create client or make request

This commit is contained in:
zhangzifa
2019-03-13 14:51:01 +08:00
committed by Jackson Tian
parent 8c9353a007
commit 619a7827de
29 changed files with 1005 additions and 97 deletions

View File

@@ -20,12 +20,7 @@
#include <sstream>
#include <string>
#include <vector>
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
namespace AlibabaCloud {
@@ -56,7 +51,6 @@ static size_t readCallback(void *ptr, size_t size, size_t nmemb, void *stream) {
return len;
}
size_t recvBody(char *ptr, size_t size, size_t nmemb, void *userdata) {
std::ostringstream &out = *static_cast<std::ostringstream*>(userdata);
out << std::string(ptr, nmemb*size);
@@ -120,49 +114,52 @@ CurlHttpClient::makeRequest(const HttpRequest &request) {
curl_easy_reset(curlHandle_);
HttpResponse response(request);
long connect_timeout = request.connectTimeout();
long read_timeout = request.readTimeout();
std::string url = request.url().toString();
switch (request.method()) {
case HttpRequest::Method::Get:
break;
case HttpRequest::Method::Post: {
if (request.bodySize() > 0) {
curl_easy_setopt(curlHandle_, CURLOPT_POSTFIELDS, request.body());
} else {
curl_easy_setopt(curlHandle_, CURLOPT_POSTFIELDS, "");
case HttpRequest::Method::Get:
break;
case HttpRequest::Method::Post: {
if (request.bodySize() > 0) {
curl_easy_setopt(curlHandle_, CURLOPT_POSTFIELDS, request.body());
} else {
curl_easy_setopt(curlHandle_, CURLOPT_POSTFIELDS, "");
}
}
}
break;
break;
case HttpRequest::Method::Put: {
uploadContext* ctx = (uploadContext *)malloc(sizeof(uploadContext));
// this is impossible, as the size is 24 Bytes
if (ctx == nullptr) {
return HttpResponseOutcome(
Error("MemoryAllocateError",
"There is not enough memory for http transfer."));
case HttpRequest::Method::Put: {
uploadContext* ctx = (uploadContext *)malloc(sizeof(uploadContext));
// this is impossible, as the size is 24 Bytes
if (ctx == nullptr) {
return HttpResponseOutcome(
Error("MemoryAllocateError",
"There is not enough memory for http transfer."));
}
ctx->data = request.body();
ctx->pos = request.body();
ctx->last = ctx->pos + request.bodySize();
curl_easy_setopt(curlHandle_, CURLOPT_READFUNCTION, readCallback);
curl_easy_setopt(curlHandle_, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(curlHandle_, CURLOPT_READDATA, ctx);
}
ctx->data = request.body();
ctx->pos = request.body();
ctx->last = ctx->pos + request.bodySize();
break;
curl_easy_setopt(curlHandle_, CURLOPT_READFUNCTION, readCallback);
curl_easy_setopt(curlHandle_, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(curlHandle_, CURLOPT_READDATA, ctx);
}
break;
case HttpRequest::Method::Delete: {
curl_easy_setopt(curlHandle_, CURLOPT_CUSTOMREQUEST, "DELETE");
if (request.bodySize() > 0) {
curl_easy_setopt(curlHandle_, CURLOPT_POSTFIELDS, request.body());
} else {
curl_easy_setopt(curlHandle_, CURLOPT_POSTFIELDS, "");
case HttpRequest::Method::Delete: {
curl_easy_setopt(curlHandle_, CURLOPT_CUSTOMREQUEST, "DELETE");
if (request.bodySize() > 0) {
curl_easy_setopt(curlHandle_, CURLOPT_POSTFIELDS, request.body());
} else {
curl_easy_setopt(curlHandle_, CURLOPT_POSTFIELDS, "");
}
}
}
break;
break;
default:
break;
default:
break;
}
curl_easy_setopt(curlHandle_, CURLOPT_URL, url.c_str());
@@ -171,6 +168,14 @@ CurlHttpClient::makeRequest(const HttpRequest &request) {
curl_easy_setopt(curlHandle_, CURLOPT_HEADERDATA, &response);
curl_easy_setopt(curlHandle_, CURLOPT_HEADERFUNCTION, recvHeaders);
if (connect_timeout > 0) {
curl_easy_setopt(curlHandle_, CURLOPT_CONNECTTIMEOUT_MS, connect_timeout);
}
if (read_timeout > 0) {
curl_easy_setopt(curlHandle_, CURLOPT_TIMEOUT_MS, read_timeout);
}
curl_slist *list = nullptr;
auto headers = request.headers();
for (const auto &p : headers) {
@@ -190,22 +195,31 @@ CurlHttpClient::makeRequest(const HttpRequest &request) {
CURLcode res = curl_easy_perform(curlHandle_);
switch (res) {
case CURLE_OK: {
long response_code;
curl_easy_getinfo(curlHandle_, CURLINFO_RESPONSE_CODE, &response_code);
response.setStatusCode(response_code);
response.setBody(out.str().c_str(), out.str().length());
return HttpResponseOutcome(response);
}
case CURLE_SSL_CONNECT_ERROR:
return HttpResponseOutcome(
Error("SSLConnectError",
"A problem occurred somewhere in the SSL/TLS handshake."));
default:
return HttpResponseOutcome(
Error("NetworkError",
"Failed to connect to host or proxy: " +
HttpMethodToString(request.method()) + " " + request.url().toString()));
case CURLE_OK: {
long response_code;
curl_easy_getinfo(curlHandle_, CURLINFO_RESPONSE_CODE, &response_code);
response.setStatusCode(response_code);
response.setBody(out.str().c_str(), out.str().length());
return HttpResponseOutcome(response);
}
case CURLE_SSL_CONNECT_ERROR:
return HttpResponseOutcome(
Error("SSLConnectError",
"A problem occurred somewhere in the SSL/TLS handshake."));
case CURLE_OPERATION_TIMEDOUT:
return HttpResponseOutcome(
Error("OperationTimeoutError",
"Timeout (connectTimeout: " +
std::to_string(connect_timeout) + "ms, readTimeout: " +
std::to_string(read_timeout) + "ms) when connect or read data: " +
HttpMethodToString(request.method()) + " " + request.url().toString()));
default: {
return HttpResponseOutcome(
Error("NetworkError",
"Failed to connect to host or proxy: " +
HttpMethodToString(request.method()) + " " + request.url().toString()));
}
}
}