static HTTPAPI_RESULT ConstructHeadersString(HTTP_HEADERS_HANDLE httpHeadersHandle, char* headers, size_t headersBufferSize) { HTTPAPI_RESULT result; size_t headersCount; headers[0] = '\0'; if (HTTPHeaders_GetHeaderCount(httpHeadersHandle, &headersCount) != HTTP_HEADERS_OK) { result = HTTPAPI_HTTP_HEADERS_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); } else { size_t i; for (i = 0; i < headersCount; i++) { char tempBuffer[TEMP_BUFFER_SIZE]; if (HTTPHeaders_GetHeader(httpHeadersHandle, i, tempBuffer, TEMP_BUFFER_SIZE) == HTTP_HEADERS_OK) { strcat_s(headers, headersBufferSize, tempBuffer); strcat_s(headers, headersBufferSize, "\r\n"); } } result = HTTPAPI_OK; } return result; }
//Note: This function assumes that "Host:" and "Content-Length:" headers are setup // by the caller of HTTPAPI_ExecuteRequest() (which is true for httptransport.c). 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) { LogInfo("HTTPAPI_ExecuteRequest::Start\r\n"); HTTPAPI_RESULT result; size_t headersCount; char buf[TEMP_BUFFER_SIZE]; int ret; TLSConnection* con = NULL; size_t bodyLength = 0; bool chunked = false; const unsigned char* receivedContent; const char* method = (requestType == HTTPAPI_REQUEST_GET) ? "GET" : (requestType == HTTPAPI_REQUEST_POST) ? "POST" : (requestType == HTTPAPI_REQUEST_PUT) ? "PUT" : (requestType == HTTPAPI_REQUEST_DELETE) ? "DELETE" : (requestType == HTTPAPI_REQUEST_PATCH) ? "PATCH" : NULL; if (handle == NULL || relativePath == NULL || httpHeadersHandle == NULL || method == NULL || HTTPHeaders_GetHeaderCount(httpHeadersHandle, &headersCount) != HTTP_HEADERS_OK) { result = HTTPAPI_INVALID_ARG; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } con = &(((HTTP_HANDLE_DATA*)handle)->con); //Send request if ((ret = snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\n", method, relativePath)) < 0 || ret >= sizeof(buf)) { result = HTTPAPI_STRING_PROCESSING_ERROR; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } LogInfo("HTTPAPI_ExecuteRequest::Sending=%*.*s\r\n", strlen(buf), strlen(buf), buf); if (con->send_all(buf, strlen(buf)) < 0) { result = HTTPAPI_SEND_REQUEST_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } //Send default headers for (int i = 0; i < (int)headersCount; i++) { if (HTTPHeaders_GetHeader(httpHeadersHandle, i, buf, sizeof(buf)) != HTTP_HEADERS_OK) { result = HTTPAPI_HTTP_HEADERS_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } LogInfo("HTTPAPI_ExecuteRequest::Sending=%*.*s\r\n", strlen(buf), strlen(buf), buf); if (con->send_all(buf, strlen(buf)) < 0) { result = HTTPAPI_SEND_REQUEST_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } if (con->send_all("\r\n", 2) < 0) { result = HTTPAPI_SEND_REQUEST_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } } //Close headers if (con->send_all("\r\n", 2) < 0) { result = HTTPAPI_SEND_REQUEST_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } //Send data (if available) if (content && contentLength > 0) { LogInfo("HTTPAPI_ExecuteRequest::Sending data=%*.*s\r\n", contentLength, contentLength, content); if (con->send_all((char*)content, contentLength) < 0) { result = HTTPAPI_SEND_REQUEST_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } } //Receive response if (readLine(con, buf, sizeof(buf)) < 0) { result = HTTPAPI_READ_DATA_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } //Parse HTTP response if (sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &ret) != 1) { //Cannot match string, error LogInfo("HTTPAPI_ExecuteRequest::Not a correct HTTP answer=%s\r\n", buf); result = HTTPAPI_READ_DATA_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } if (statusCode) *statusCode = ret; LogInfo("HTTPAPI_ExecuteRequest::Received response=%*.*s\r\n", strlen(buf), strlen(buf), buf); //Read HTTP response headers if (readLine(con, buf, sizeof(buf)) < 0) { result = HTTPAPI_READ_DATA_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } while (buf[0]) { const char ContentLength[] = "content-length:"; const char TransferEncoding[] = "transfer-encoding:"; LogInfo("Receiving header=%*.*s\r\n", strlen(buf), strlen(buf), buf); if (strncasecmp(buf, ContentLength, CHAR_COUNT(ContentLength)) == 0) { if (sscanf(buf + CHAR_COUNT(ContentLength), " %d", &bodyLength) != 1) { result = HTTPAPI_READ_DATA_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } } else if (strncasecmp(buf, TransferEncoding, CHAR_COUNT(TransferEncoding)) == 0) { const char* p = buf + CHAR_COUNT(TransferEncoding); while (isspace(*p)) p++; if (strcasecmp(p, "chunked") == 0) chunked = true; } char* whereIsColon = strchr((char*)buf, ':'); if (whereIsColon && responseHeadersHandle != NULL) { *whereIsColon = '\0'; HTTPHeaders_AddHeaderNameValuePair(responseHeadersHandle, buf, whereIsColon + 1); } if (readLine(con, buf, sizeof(buf)) < 0) { result = HTTPAPI_READ_DATA_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } } //Read HTTP response body LogInfo("HTTPAPI_ExecuteRequest::Receiving body=%d,%x\r\n", bodyLength, responseContent); if (!chunked) { if (bodyLength) { if (responseContent != NULL) { if (BUFFER_pre_build(responseContent, bodyLength) != 0) { result = HTTPAPI_ALLOC_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); } else if (BUFFER_content(responseContent, &receivedContent) != 0) { (void)BUFFER_unbuild(responseContent); result = HTTPAPI_ALLOC_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); } if (readChunk(con, (char*)receivedContent, bodyLength) < 0) { result = HTTPAPI_READ_DATA_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } else { LogInfo("HTTPAPI_ExecuteRequest::Received response body=%*.*s\r\n", bodyLength, bodyLength, receivedContent); result = HTTPAPI_OK; } } else { (void)skipN(con, bodyLength, buf, sizeof(buf)); result = HTTPAPI_OK; } } else { result = HTTPAPI_OK; } } else { size_t size = 0; result = HTTPAPI_OK; for (;;) { int chunkSize; if (readLine(con, buf, sizeof(buf)) < 0) // read [length in hex]/r/n { result = HTTPAPI_READ_DATA_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } if (sscanf(buf, "%x", &chunkSize) != 1) // chunkSize is length of next line (/r/n is not counted) { //Cannot match string, error result = HTTPAPI_RECEIVE_RESPONSE_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } if (chunkSize == 0) { // 0 length means next line is just '\r\n' and end of chunks if (readChunk(con, (char*)buf, 2) < 0 || buf[0] != '\r' || buf[1] != '\n') // skip /r/n { (void)BUFFER_unbuild(responseContent); result = HTTPAPI_READ_DATA_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } break; } else { if (responseContent != NULL) { if (BUFFER_enlarge(responseContent, chunkSize) != 0) { (void)BUFFER_unbuild(responseContent); result = HTTPAPI_ALLOC_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); } else if (BUFFER_content(responseContent, &receivedContent) != 0) { (void)BUFFER_unbuild(responseContent); result = HTTPAPI_ALLOC_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); } if (readChunk(con, (char*)receivedContent + size, chunkSize) < 0) { result = HTTPAPI_READ_DATA_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } } else { if (skipN(con, chunkSize, buf, sizeof(buf)) < 0) { result = HTTPAPI_READ_DATA_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } } if (readChunk(con, (char*)buf, 2) < 0 || buf[0] != '\r' || buf[1] != '\n') // skip /r/n { result = HTTPAPI_READ_DATA_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } size += chunkSize; } } if (size > 0) { LogInfo("HTTPAPI_ExecuteRequest::Received chunk body=%*.*s\r\n", size, size, responseContent); } } exit: LogInfo("HTTPAPI_ExecuteRequest::End=%d\r\n", result); return result; }
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) { int result; size_t headersCount; char* header; HTTPSClient* client = (HTTPSClient*)handle; if (!client->connected()) { // client not connected LogError("HTTPS request failed, client not connected\n"); return HTTPAPI_OPEN_REQUEST_FAILED; } result = client->sendRequest(HTTPRequestTypes[requestType], relativePath); if (!result) { LogError("HTTPS send request failed\n"); return HTTPAPI_SEND_REQUEST_FAILED; } HTTPHeaders_GetHeaderCount(httpHeadersHandle, &headersCount); for (size_t i = 0; i < headersCount && result; i++) { HTTPHeaders_GetHeader(httpHeadersHandle, i, &header); result = client->sendHeader(header); free(header); } if (!result) { LogError("HTTPS send header failed\n"); return HTTPAPI_SEND_REQUEST_FAILED; } result = client->sendBody(content, contentLength); if (!result) { LogError("HTTPS send body failed\n"); return HTTPAPI_SEND_REQUEST_FAILED; } result = client->readStatus(); if (result == -1) { return HTTPAPI_STRING_PROCESSING_ERROR; } *statusCode = result; while (result > 0) { String headerName; String headerValue; result = client->readHeader(headerName, headerValue); HTTPHeaders_AddHeaderNameValuePair(responseHeadersHandle, headerName.c_str(), headerValue.c_str()); } if (result == -1) { LogError("HTTPS header parsing failed\n"); return HTTPAPI_HTTP_HEADERS_FAILED; } contentLength = client->contentLength(); if (contentLength) { BUFFER_pre_build(responseContent, contentLength); client->readBody(BUFFER_u_char(responseContent), contentLength); } return HTTPAPI_OK; }
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 = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result)); } else if (HTTPHeaders_GetHeaderCount(httpHeadersHandle, &headersCount) != HTTP_HEADERS_OK) { result = HTTPAPI_INVALID_ARG; LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result)); } else { char* tempHostURL; size_t tempHostURL_size = strlen(httpHandleData->hostURL) + strlen(relativePath) + 1; tempHostURL = malloc(tempHostURL_size); if (tempHostURL == NULL) { result = HTTPAPI_ERROR; LogError("(result = %s)", ENUM_TO_STRING(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 = %s)", ENUM_TO_STRING(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 = %s)", ENUM_TO_STRING(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 = %s)", ENUM_TO_STRING(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 = %s)", ENUM_TO_STRING(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 = %s)", ENUM_TO_STRING(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 = %s)", ENUM_TO_STRING(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 = %s)", ENUM_TO_STRING(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 = %s)", ENUM_TO_STRING(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 = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result)); } else { result = HTTPAPI_OK; switch (requestType) { default: result = HTTPAPI_INVALID_ARG; LogError("(result = %s)", ENUM_TO_STRING(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 = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result)); } else { if (curl_easy_setopt(httpHandleData->curl, CURLOPT_CUSTOMREQUEST, NULL) != CURLE_OK) { result = HTTPAPI_SET_OPTION_FAILED; LogError("(result = %s)", ENUM_TO_STRING(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 = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result)); } else { if (curl_easy_setopt(httpHandleData->curl, CURLOPT_CUSTOMREQUEST, NULL) != CURLE_OK) { result = HTTPAPI_SET_OPTION_FAILED; LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result)); } } break; case HTTPAPI_REQUEST_PUT: if (curl_easy_setopt(httpHandleData->curl, CURLOPT_POST, 1L)) { result = HTTPAPI_SET_OPTION_FAILED; LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result)); } else { if (curl_easy_setopt(httpHandleData->curl, CURLOPT_CUSTOMREQUEST, "PUT") != CURLE_OK) { result = HTTPAPI_SET_OPTION_FAILED; LogError("(result = %s)", ENUM_TO_STRING(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 = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result)); } else { if (curl_easy_setopt(httpHandleData->curl, CURLOPT_CUSTOMREQUEST, "DELETE") != CURLE_OK) { result = HTTPAPI_SET_OPTION_FAILED; LogError("(result = %s)", ENUM_TO_STRING(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 = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result)); } else { if (curl_easy_setopt(httpHandleData->curl, CURLOPT_CUSTOMREQUEST, "PATCH") != CURLE_OK) { result = HTTPAPI_SET_OPTION_FAILED; LogError("(result = %s)", ENUM_TO_STRING(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 = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result)); break; } else { struct curl_slist* newHeaders = curl_slist_append(headers, tempBuffer); if (newHeaders == NULL) { result = HTTPAPI_ALLOC_FAILED; LogError("(result = %s)", ENUM_TO_STRING(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 = %s)", ENUM_TO_STRING(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 = %s)", ENUM_TO_STRING(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 = %s)", ENUM_TO_STRING(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 = %s)", ENUM_TO_STRING(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 = %s)", ENUM_TO_STRING(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 = %s)", ENUM_TO_STRING(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 = %s)", ENUM_TO_STRING(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 = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result)); } else if (responseContentBuffer.error) { result = HTTPAPI_READ_DATA_FAILED; LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result)); } else { if (statusCode != NULL) { *statusCode = 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 = %s)", ENUM_TO_STRING(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); } } } } } } curl_slist_free_all(headers); } } free(tempHostURL); } } return result; }
/*returns NULL if it failed to construct the headers*/ static const char* ConstructHeadersString(HTTP_HEADERS_HANDLE httpHeadersHandle) { char* result; size_t headersCount; if (HTTPHeaders_GetHeaderCount(httpHeadersHandle, &headersCount) != HTTP_HEADERS_OK) { result = NULL; LogError("HTTPHeaders_GetHeaderCount failed."); } else { size_t i; /*the total size of all the headers is given by sumof(lengthof(everyheader)+2)*/ size_t toAlloc = 0; for (i = 0; i < headersCount; i++) { char *temp; if (HTTPHeaders_GetHeader(httpHeadersHandle, i, &temp) == HTTP_HEADERS_OK) { toAlloc += strlen(temp); toAlloc += 2; free(temp); } else { LogError("HTTPHeaders_GetHeader failed"); break; } } if (i < headersCount) { result = NULL; } else { result = (char*)malloc(toAlloc*sizeof(char) + 1 ); if (result == NULL) { LogError("unable to malloc"); /*let it be returned*/ } else { result[0] = '\0'; for (i = 0; i < headersCount; i++) { char* temp; if (HTTPHeaders_GetHeader(httpHeadersHandle, i, &temp) != HTTP_HEADERS_OK) { LogError("unable to HTTPHeaders_GetHeader"); break; } else { (void)strcat(result, temp); (void)strcat(result, "\r\n"); free(temp); } } if (i < headersCount) { free(result); result = NULL; } else { /*all is good*/ } } } } return result; }