static STSStatus setup_curl(Request* request, RequestParams* params) { STSStatus status; #define curl_easy_setopt_safe(opt, val) \ if ((status = curl_easy_setopt \ (request->curl, opt, val)) != CURLE_OK) { \ return STSStatusFailedToInitRequest; \ } curl_easy_setopt_safe(CURLOPT_PRIVATE, request); curl_easy_setopt_safe(CURLOPT_URL, request->uri); //curl_easy_setopt_safe(CURLOPT_SSL_VERIFYPEER, 0); //curl_easy_setopt_safe(CURLOPT_SSL_VERIFYHOST, 0); //curl_easy_setopt_safe(CURLOPT_VERBOSE, 1); curl_easy_setopt_safe(CURLOPT_TIMEOUT, STS_HTTP_TIMEOUT); curl_easy_setopt_safe(CURLOPT_POST, 1); curl_easy_setopt_safe(CURLOPT_POSTFIELDS, params->postData); curl_easy_setopt_safe(CURLOPT_POSTFIELDSIZE, strlen(params->postData)); // Set write callback and data curl_easy_setopt_safe(CURLOPT_WRITEFUNCTION, &curl_write_func); curl_easy_setopt_safe(CURLOPT_WRITEDATA, request); request->headers = curl_slist_append(request->headers, "Content-Type: application/x-www-form-urlencoded"); curl_easy_setopt(request->curl, CURLOPT_HTTPHEADER, request->headers); return status; }
// Sets up the curl handle given the completely computed RequestParams static S3Status setup_curl(Request *request, const RequestParams *params, const RequestComputedValues *values) { CURLcode status; #define curl_easy_setopt_safe(opt, val) \ if ((status = curl_easy_setopt \ (request->curl, opt, val)) != CURLE_OK) { \ return S3StatusFailedToInitializeRequest; \ } // Debugging only // curl_easy_setopt_safe(CURLOPT_VERBOSE, 1); // Set private data to request for the benefit of S3RequestContext curl_easy_setopt_safe(CURLOPT_PRIVATE, request); // Set header callback and data curl_easy_setopt_safe(CURLOPT_HEADERDATA, request); curl_easy_setopt_safe(CURLOPT_HEADERFUNCTION, &curl_header_func); // Set read callback, data, and readSize curl_easy_setopt_safe(CURLOPT_READFUNCTION, &curl_read_func); curl_easy_setopt_safe(CURLOPT_READDATA, request); // Set write callback and data curl_easy_setopt_safe(CURLOPT_WRITEFUNCTION, &curl_write_func); curl_easy_setopt_safe(CURLOPT_WRITEDATA, request); // Ask curl to parse the Last-Modified header. This is easier than // parsing it ourselves. curl_easy_setopt_safe(CURLOPT_FILETIME, 1); // Curl docs suggest that this is necessary for multithreaded code. // However, it also points out that DNS timeouts will not be honored // during DNS lookup, which can be worked around by using the c-ares // library, which we do not do yet. curl_easy_setopt_safe(CURLOPT_NOSIGNAL, 1); // Turn off Curl's built-in progress meter curl_easy_setopt_safe(CURLOPT_NOPROGRESS, 1); // xxx todo - support setting the proxy for Curl to use (can't use https // for proxies though) // xxx todo - support setting the network interface for Curl to use // I think this is useful - we don't need interactive performance, we need // to complete large operations quickly curl_easy_setopt_safe(CURLOPT_TCP_NODELAY, 1); // Don't use Curl's 'netrc' feature curl_easy_setopt_safe(CURLOPT_NETRC, CURL_NETRC_IGNORED); // Don't verify S3's certificate, there are known to be issues with // them sometimes // xxx todo - support an option for verifying the S3 CA (default false) curl_easy_setopt_safe(CURLOPT_SSL_VERIFYPEER, 0); // Follow any redirection directives that S3 sends curl_easy_setopt_safe(CURLOPT_FOLLOWLOCATION, 1); // A safety valve in case S3 goes bananas with redirects curl_easy_setopt_safe(CURLOPT_MAXREDIRS, 10); // Set the User-Agent; maybe Amazon will track these? curl_easy_setopt_safe(CURLOPT_USERAGENT, userAgentG); // Set the low speed limit and time; we abort transfers that stay at // less than 1K per second for more than 15 seconds. // xxx todo - make these configurable // xxx todo - allow configurable max send and receive speed curl_easy_setopt_safe(CURLOPT_LOW_SPEED_LIMIT, 1024); curl_easy_setopt_safe(CURLOPT_LOW_SPEED_TIME, 15); // Append standard headers #define append_standard_header(fieldName) \ if (values-> fieldName [0]) { \ request->headers = curl_slist_append(request->headers, \ values-> fieldName); \ } // Would use CURLOPT_INFILESIZE_LARGE, but it is buggy in libcurl if (params->httpRequestType == HttpRequestTypePUT) { char header[256]; snprintf(header, sizeof(header), "Content-Length: %llu", (unsigned long long) params->toS3CallbackTotalSize); request->headers = curl_slist_append(request->headers, header); request->headers = curl_slist_append(request->headers, "Transfer-Encoding:"); } else if (params->httpRequestType == HttpRequestTypeCOPY) { request->headers = curl_slist_append(request->headers, "Transfer-Encoding:"); } append_standard_header(cacheControlHeader); append_standard_header(contentTypeHeader); append_standard_header(md5Header); append_standard_header(contentDispositionHeader); append_standard_header(contentEncodingHeader); append_standard_header(expiresHeader); append_standard_header(ifModifiedSinceHeader); append_standard_header(ifUnmodifiedSinceHeader); append_standard_header(ifMatchHeader); append_standard_header(ifNoneMatchHeader); append_standard_header(rangeHeader); append_standard_header(authorizationHeader); // Append x-amz- headers int i; for (i = 0; i < values->amzHeadersCount; i++) { request->headers = curl_slist_append(request->headers, values->amzHeaders[i]); } // Set the HTTP headers curl_easy_setopt_safe(CURLOPT_HTTPHEADER, request->headers); // Set URI curl_easy_setopt_safe(CURLOPT_URL, request->uri); // Set request type. switch (params->httpRequestType) { case HttpRequestTypeHEAD: curl_easy_setopt_safe(CURLOPT_NOBODY, 1); break; case HttpRequestTypePUT: case HttpRequestTypeCOPY: curl_easy_setopt_safe(CURLOPT_UPLOAD, 1); break; case HttpRequestTypeDELETE: curl_easy_setopt_safe(CURLOPT_CUSTOMREQUEST, "DELETE"); break; default: // HttpRequestTypeGET break; } return S3StatusOK; }
int aos_curl_transport_setup(aos_curl_http_transport_t *t) { CURLcode code; #define curl_easy_setopt_safe(opt, val) \ if ((code = curl_easy_setopt(t->curl, opt, val)) != CURLE_OK) { \ t->controller->reason = apr_pstrdup(t->pool, curl_easy_strerror(code)); \ t->controller->error_code = AOSE_FAILED_INITIALIZE; \ aos_error_log("curl_easy_setopt failed, code:%d %s.", code, t->controller->reason); \ return AOSE_FAILED_INITIALIZE; \ } curl_easy_setopt_safe(CURLOPT_PRIVATE, t); curl_easy_setopt_safe(CURLOPT_HEADERDATA, t); curl_easy_setopt_safe(CURLOPT_HEADERFUNCTION, t->header_callback); curl_easy_setopt_safe(CURLOPT_READDATA, t); curl_easy_setopt_safe(CURLOPT_READFUNCTION, t->read_callback); curl_easy_setopt_safe(CURLOPT_WRITEDATA, t); curl_easy_setopt_safe(CURLOPT_WRITEFUNCTION, t->write_callback); curl_easy_setopt_safe(CURLOPT_FILETIME, 1); curl_easy_setopt_safe(CURLOPT_NOSIGNAL, 1); curl_easy_setopt_safe(CURLOPT_NOPROGRESS, 1); curl_easy_setopt_safe(CURLOPT_TCP_NODELAY, 1); curl_easy_setopt_safe(CURLOPT_NETRC, CURL_NETRC_IGNORED); // transport options curl_easy_setopt_safe(CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt_safe(CURLOPT_USERAGENT, t->options->user_agent); // request options curl_easy_setopt_safe(CURLOPT_DNS_CACHE_TIMEOUT, t->controller->options->dns_cache_timeout); curl_easy_setopt_safe(CURLOPT_CONNECTTIMEOUT, t->controller->options->connect_timeout); curl_easy_setopt_safe(CURLOPT_LOW_SPEED_LIMIT, t->controller->options->speed_limit); curl_easy_setopt_safe(CURLOPT_LOW_SPEED_TIME, t->controller->options->speed_time); aos_init_curl_headers(t); curl_easy_setopt_safe(CURLOPT_HTTPHEADER, t->headers); if (NULL == t->req->signed_url) { if (aos_init_curl_url(t) != AOSE_OK) { return t->controller->error_code; } } else { t->url = t->req->signed_url; } curl_easy_setopt_safe(CURLOPT_URL, t->url); switch (t->req->method) { case HTTP_HEAD: curl_easy_setopt_safe(CURLOPT_NOBODY, 1); break; case HTTP_PUT: curl_easy_setopt_safe(CURLOPT_UPLOAD, 1); break; case HTTP_POST: curl_easy_setopt_safe(CURLOPT_POST, 1); break; case HTTP_DELETE: curl_easy_setopt_safe(CURLOPT_CUSTOMREQUEST, "DELETE"); break; default: // HTTP_GET break; } #undef curl_easy_setopt_safe t->state = TRANS_STATE_INIT; return AOSE_OK; }