in adapters/httpapi_curl.c [499:889]
HTTPAPI_RESULT HTTPAPI_ExecuteRequest(HTTP_HANDLE handle, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath,
HTTP_HEADERS_HANDLE httpHeadersHandle, const unsigned char* content,
size_t contentLength, unsigned int* statusCode,
HTTP_HEADERS_HANDLE responseHeadersHandle, BUFFER_HANDLE responseContent)
{
HTTPAPI_RESULT result;
HTTP_HANDLE_DATA* httpHandleData = (HTTP_HANDLE_DATA*)handle;
size_t headersCount;
HTTP_RESPONSE_CONTENT_BUFFER responseContentBuffer;
if ((httpHandleData == NULL) ||
(relativePath == NULL) ||
(httpHeadersHandle == NULL) ||
((content == NULL) && (contentLength > 0))
)
{
result = HTTPAPI_INVALID_ARG;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
else if (HTTPHeaders_GetHeaderCount(httpHeadersHandle, &headersCount) != HTTP_HEADERS_OK)
{
result = HTTPAPI_INVALID_ARG;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
else
{
char* tempHostURL;
size_t tempHostURL_size = safe_add_size_t(strlen(httpHandleData->hostURL), strlen(relativePath));
tempHostURL_size = safe_add_size_t(tempHostURL_size, 1);
if (tempHostURL_size == SIZE_MAX)
{
LogError("Invalid malloc size");
tempHostURL = NULL;
}
else
{
tempHostURL = malloc(tempHostURL_size);
}
if (tempHostURL == NULL)
{
result = HTTPAPI_ERROR;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
else
{
if (curl_easy_setopt(httpHandleData->curl, CURLOPT_VERBOSE, httpHandleData->verbose) != CURLE_OK)
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("failed to set CURLOPT_VERBOSE (result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
else if ((strcpy_s(tempHostURL, tempHostURL_size, httpHandleData->hostURL) != 0) ||
(strcat_s(tempHostURL, tempHostURL_size, relativePath) != 0))
{
result = HTTPAPI_STRING_PROCESSING_ERROR;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
/* set the URL */
else if (curl_easy_setopt(httpHandleData->curl, CURLOPT_URL, tempHostURL) != CURLE_OK)
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("failed to set CURLOPT_URL (result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
else if (curl_easy_setopt(httpHandleData->curl, CURLOPT_TIMEOUT_MS, httpHandleData->timeout) != CURLE_OK)
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("failed to set CURLOPT_TIMEOUT_MS (result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
else if (curl_easy_setopt(httpHandleData->curl, CURLOPT_LOW_SPEED_LIMIT, httpHandleData->lowSpeedLimit) != CURLE_OK)
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("failed to set CURLOPT_LOW_SPEED_LIMIT (result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
else if (curl_easy_setopt(httpHandleData->curl, CURLOPT_LOW_SPEED_TIME, httpHandleData->lowSpeedTime) != CURLE_OK)
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("failed to set CURLOPT_LOW_SPEED_TIME (result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
else if (curl_easy_setopt(httpHandleData->curl, CURLOPT_FRESH_CONNECT, httpHandleData->freshConnect) != CURLE_OK)
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("failed to set CURLOPT_FRESH_CONNECT (result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
else if (curl_easy_setopt(httpHandleData->curl, CURLOPT_FORBID_REUSE, httpHandleData->forbidReuse) != CURLE_OK)
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("failed to set CURLOPT_FORBID_REUSE (result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
else if (curl_easy_setopt(httpHandleData->curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1) != CURLE_OK)
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("failed to set CURLOPT_HTTP_VERSION (result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
else
{
result = HTTPAPI_OK;
switch (requestType)
{
default:
result = HTTPAPI_INVALID_ARG;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
break;
case HTTPAPI_REQUEST_GET:
if (curl_easy_setopt(httpHandleData->curl, CURLOPT_HTTPGET, 1L) != CURLE_OK)
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
else
{
if (curl_easy_setopt(httpHandleData->curl, CURLOPT_CUSTOMREQUEST, NULL) != CURLE_OK)
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
}
break;
case HTTPAPI_REQUEST_HEAD:
if (curl_easy_setopt(httpHandleData->curl, CURLOPT_HTTPGET, 1L) != CURLE_OK)
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
else if (curl_easy_setopt(httpHandleData->curl, CURLOPT_NOBODY, 1L) != CURLE_OK)
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
else if (curl_easy_setopt(httpHandleData->curl, CURLOPT_CUSTOMREQUEST, NULL) != CURLE_OK)
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
break;
case HTTPAPI_REQUEST_POST:
if (curl_easy_setopt(httpHandleData->curl, CURLOPT_POST, 1L) != CURLE_OK)
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
else
{
if (curl_easy_setopt(httpHandleData->curl, CURLOPT_CUSTOMREQUEST, NULL) != CURLE_OK)
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
}
break;
case HTTPAPI_REQUEST_PUT:
if (curl_easy_setopt(httpHandleData->curl, CURLOPT_POST, 1L))
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
else
{
if (curl_easy_setopt(httpHandleData->curl, CURLOPT_CUSTOMREQUEST, "PUT") != CURLE_OK)
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
}
break;
case HTTPAPI_REQUEST_DELETE:
if (curl_easy_setopt(httpHandleData->curl, CURLOPT_POST, 1L) != CURLE_OK)
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
else
{
if (curl_easy_setopt(httpHandleData->curl, CURLOPT_CUSTOMREQUEST, "DELETE") != CURLE_OK)
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
}
break;
case HTTPAPI_REQUEST_PATCH:
if (curl_easy_setopt(httpHandleData->curl, CURLOPT_POST, 1L) != CURLE_OK)
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
else
{
if (curl_easy_setopt(httpHandleData->curl, CURLOPT_CUSTOMREQUEST, "PATCH") != CURLE_OK)
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
}
break;
}
if (result == HTTPAPI_OK)
{
/* add headers */
struct curl_slist* headers = NULL;
size_t i;
for (i = 0; i < headersCount; i++)
{
char *tempBuffer;
if (HTTPHeaders_GetHeader(httpHeadersHandle, i, &tempBuffer) != HTTP_HEADERS_OK)
{
/* error */
result = HTTPAPI_HTTP_HEADERS_FAILED;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
break;
}
else
{
struct curl_slist* newHeaders = curl_slist_append(headers, tempBuffer);
if (newHeaders == NULL)
{
result = HTTPAPI_ALLOC_FAILED;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
free(tempBuffer);
break;
}
else
{
free(tempBuffer);
headers = newHeaders;
}
}
}
if (result == HTTPAPI_OK)
{
if (curl_easy_setopt(httpHandleData->curl, CURLOPT_HTTPHEADER, headers) != CURLE_OK)
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
else
{
/* add content */
if ((content != NULL) &&
(contentLength > 0))
{
if ((curl_easy_setopt(httpHandleData->curl, CURLOPT_POSTFIELDS, (void*)content) != CURLE_OK) ||
(curl_easy_setopt(httpHandleData->curl, CURLOPT_POSTFIELDSIZE, contentLength) != CURLE_OK))
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
}
else
{
if (requestType != HTTPAPI_REQUEST_GET)
{
if ((curl_easy_setopt(httpHandleData->curl, CURLOPT_POSTFIELDS, (void*)NULL) != CURLE_OK) ||
(curl_easy_setopt(httpHandleData->curl, CURLOPT_POSTFIELDSIZE, 0) != CURLE_OK))
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
}
else
{
/*GET request cannot POST, so "do nothing*/
}
}
if (result == HTTPAPI_OK)
{
if ((curl_easy_setopt(httpHandleData->curl, CURLOPT_WRITEHEADER, NULL) != CURLE_OK) ||
(curl_easy_setopt(httpHandleData->curl, CURLOPT_HEADERFUNCTION, NULL) != CURLE_OK) ||
(curl_easy_setopt(httpHandleData->curl, CURLOPT_WRITEFUNCTION, ContentWriteFunction) != CURLE_OK))
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
else
{
if (responseHeadersHandle != NULL)
{
/* setup the code to get the response headers */
if ((curl_easy_setopt(httpHandleData->curl, CURLOPT_WRITEHEADER, responseHeadersHandle) != CURLE_OK) ||
(curl_easy_setopt(httpHandleData->curl, CURLOPT_HEADERFUNCTION, HeadersWriteFunction) != CURLE_OK))
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
}
if (result == HTTPAPI_OK)
{
responseContentBuffer.buffer = NULL;
responseContentBuffer.bufferSize = 0;
responseContentBuffer.error = 0;
if (curl_easy_setopt(httpHandleData->curl, CURLOPT_WRITEDATA, &responseContentBuffer) != CURLE_OK)
{
result = HTTPAPI_SET_OPTION_FAILED;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
if (result == HTTPAPI_OK)
{
/* Execute request */
CURLcode curlRes = curl_easy_perform(httpHandleData->curl);
if (curlRes != CURLE_OK)
{
LogError("curl_easy_perform() failed: %s\n", curl_easy_strerror(curlRes));
result = HTTPAPI_OPEN_REQUEST_FAILED;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
else
{
long httpCode;
/* get the status code */
if (curl_easy_getinfo(httpHandleData->curl, CURLINFO_RESPONSE_CODE, &httpCode) != CURLE_OK)
{
result = HTTPAPI_QUERY_HEADERS_FAILED;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
else if (responseContentBuffer.error)
{
result = HTTPAPI_READ_DATA_FAILED;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
else
{
if (statusCode != NULL)
{
*statusCode = (unsigned int)httpCode;
}
/* fill response content length */
if (responseContent != NULL)
{
if ((responseContentBuffer.bufferSize > 0) && (BUFFER_build(responseContent, responseContentBuffer.buffer, responseContentBuffer.bufferSize) != 0))
{
result = HTTPAPI_INSUFFICIENT_RESPONSE_BUFFER;
LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
}
else
{
/*all nice*/
}
}
if (httpCode >= 300)
{
LogError("Failure in HTTP communication: server reply code is %ld", httpCode);
LogInfo("HTTP Response:%*.*s", (int)responseContentBuffer.bufferSize,
(int)responseContentBuffer.bufferSize, responseContentBuffer.buffer);
}
else
{
result = HTTPAPI_OK;
}
}
}
}
if (responseContentBuffer.buffer != NULL)
{
free(responseContentBuffer.buffer);
responseContentBuffer.buffer = NULL;
}
}
}
}
}
}
curl_slist_free_all(headers);
}
}
free(tempHostURL);
}
}
return result;
}