+ r->_client = this;
+
+#if defined(ENABLE_CURL)
+ ClientPrivate::RequestCurlMap::iterator rit = d->requests.find(r);
+ assert(rit == d->requests.end());
+
+ CURL* curlRequest = curl_easy_init();
+ curl_easy_setopt(curlRequest, CURLOPT_URL, r->url().c_str());
+
+ d->requests[r] = curlRequest;
+
+ curl_easy_setopt(curlRequest, CURLOPT_PRIVATE, r.get());
+ // disable built-in libCurl progress feedback
+ curl_easy_setopt(curlRequest, CURLOPT_NOPROGRESS, 1);
+
+ curl_easy_setopt(curlRequest, CURLOPT_WRITEFUNCTION, requestWriteCallback);
+ curl_easy_setopt(curlRequest, CURLOPT_WRITEDATA, r.get());
+ curl_easy_setopt(curlRequest, CURLOPT_HEADERFUNCTION, requestHeaderCallback);
+ curl_easy_setopt(curlRequest, CURLOPT_HEADERDATA, r.get());
+
+ curl_easy_setopt(curlRequest, CURLOPT_USERAGENT, d->userAgent.c_str());
+ curl_easy_setopt(curlRequest, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+
+ if (!d->proxy.empty()) {
+ curl_easy_setopt(curlRequest, CURLOPT_PROXY, d->proxy.c_str());
+ curl_easy_setopt(curlRequest, CURLOPT_PROXYPORT, d->proxyPort);
+
+ if (!d->proxyAuth.empty()) {
+ curl_easy_setopt(curlRequest, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
+ curl_easy_setopt(curlRequest, CURLOPT_PROXYUSERPWD, d->proxyAuth.c_str());
+ }
+ }
+
+ std::string method = boost::to_lower_copy(r->method());
+ if (method == "get") {
+ curl_easy_setopt(curlRequest, CURLOPT_HTTPGET, 1);
+ } else if (method == "put") {
+ curl_easy_setopt(curlRequest, CURLOPT_PUT, 1);
+ curl_easy_setopt(curlRequest, CURLOPT_UPLOAD, 1);
+ } else if (method == "post") {
+ // see http://curl.haxx.se/libcurl/c/CURLOPT_POST.html
+ curl_easy_setopt(curlRequest, CURLOPT_HTTPPOST, 1);
+
+ std::string q = r->query().substr(1);
+ curl_easy_setopt(curlRequest, CURLOPT_COPYPOSTFIELDS, q.c_str());
+
+ // reset URL to exclude query pieces
+ std::string urlWithoutQuery = r->url();
+ std::string::size_type queryPos = urlWithoutQuery.find('?');
+ urlWithoutQuery.resize(queryPos);
+ curl_easy_setopt(curlRequest, CURLOPT_URL, urlWithoutQuery.c_str());
+ } else {
+ curl_easy_setopt(curlRequest, CURLOPT_CUSTOMREQUEST, r->method().c_str());
+ }
+
+ struct curl_slist* headerList = NULL;
+ if (r->hasBodyData() && (method != "post")) {
+ curl_easy_setopt(curlRequest, CURLOPT_UPLOAD, 1);
+ curl_easy_setopt(curlRequest, CURLOPT_INFILESIZE, r->bodyLength());
+ curl_easy_setopt(curlRequest, CURLOPT_READFUNCTION, requestReadCallback);
+ curl_easy_setopt(curlRequest, CURLOPT_READDATA, r.get());
+ std::string h = "Content-Type:" + r->bodyType();
+ headerList = curl_slist_append(headerList, h.c_str());
+ }
+
+ StringMap::const_iterator it;
+ for (it = r->requestHeaders().begin(); it != r->requestHeaders().end(); ++it) {
+ std::string h = it->first + ": " + it->second;
+ headerList = curl_slist_append(headerList, h.c_str());
+ }
+
+ if (headerList != NULL) {
+ curl_easy_setopt(curlRequest, CURLOPT_HTTPHEADER, headerList);
+ }
+
+ curl_multi_add_handle(d->curlMulti, curlRequest);
+
+// this seems premature, but we don't have a callback from Curl we could
+// use to trigger when the requst is actually sent.
+ r->requestStart();
+
+#else
+ if( r->url().find("http://") != 0 ) {
+ r->setFailure(EINVAL, "only HTTP protocol is supported");
+ return;
+ }
+
+ std::string host = r->host();