bool CurlHttpClient::execute(const internal::HttpRequest& request, internal::HttpResponse& response) { CURLStatus_ = CURLE_FAILED_INIT; errorBuf_[0] = '\0'; bool retry(false); unsigned retryCount(0); response.clear(); CURL* curl = curl_easy_init(); if (NULL == curl) { return (internal::HttpResponse::HTTP_OK == response.getHttpStatus()); } std::string URI(getRequestString(request)); FREDCPP_LOG_DEBUG("CURL:URI:" << URI); if (!CACertFile_.empty()) { std::ifstream ifs(CACertFile_.c_str()); FREDCPP_LOG_DEBUG("CURL:CACertFile:" << CACertFile_ << " found:" << ifs.good()); } if (CURLE_OK == (CURLStatus_ = curl_easy_setopt(curl, CURLOPT_USERAGENT, userAgent_.c_str())) && CURLE_OK == (CURLStatus_ = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeDataCallback_)) && CURLE_OK == (CURLStatus_ = curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L)) && CURLE_OK == (CURLStatus_ = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L)) && CURLE_OK == (CURLStatus_ = curl_easy_setopt(curl, CURLOPT_FILE, &response.getContentStream())) && CURLE_OK == (CURLStatus_ = curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeoutSecs_)) && CURLE_OK == (CURLStatus_ = curl_easy_setopt(curl, CURLOPT_URL, URI.c_str())) && CURLE_OK == (CURLStatus_ = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuf_)) && (!request.isHttps() || CURLE_OK == (CURLStatus_ = curl_easy_setopt(curl, CURLOPT_CAINFO, CACertFile_.c_str()))) ) { do { CURLStatus_ = curl_easy_perform(curl); if (CURLE_OK == CURLStatus_) { // on successfull call get http-status and content-type long code(0L); char *strInfo(NULL); if (CURLE_OK == curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code) && CURLE_OK == curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &strInfo)) { response.setHttpStatus(httpStatusFromCode(code)); response.setContentType(strInfo); } } else { FREDCPP_LOG_DEBUG("CURL:Request failed CURLStatus:" << CURLStatus_ << "|" << errorBuf_); } retry = (CURLE_OPERATION_TIMEDOUT == CURLStatus_ || CURLE_COULDNT_RESOLVE_HOST == CURLStatus_ || CURLE_COULDNT_RESOLVE_PROXY == CURLStatus_ || CURLE_COULDNT_CONNECT == CURLStatus_); if (retry) { if (retryCount < retryMaxCount_) { ++retryCount; FREDCPP_LOG_DEBUG("CURL:Waiting " << retryWaitSecs_ << "ms" << " before request retry " << retryCount << " ..."); internal::sleep(retryWaitSecs_); } else { retry = false; FREDCPP_LOG_DEBUG("CURL:Retry maximum count " << retryMaxCount_ << " reached - giving up."); } } } while (retry); } if (CURLE_OK == CURLStatus_) { FREDCPP_LOG_DEBUG("CURL:http-response:" << response.getHttpStatus() << " " << "content-type:" << response.getContentType()); } curl_easy_cleanup(curl); return (internal::HttpResponse::HTTP_OK == response.getHttpStatus()); }
bool Api::get(const ApiRequest& request, ApiResponse& response) { response.clear(); // validate bool requireValidExecutor(executor_ != NULL); if (!requireValidExecutor) { assert(requireValidExecutor && "Valid HttpRequestExecutor implementation expected."); response.setError( FatalInternalError("Api Executor is not set.") ); return (response.good()); } bool requireValidParser(parser_ != NULL); if (!requireValidParser) { assert(requireValidParser && "Valid XmlResponseParser implementation expected."); response.setError( FatalInternalError("Api Parser is not set.") ); return (response.good()); } FREDCPP_LOG_DEBUG("request:" << request); // prepare request (ApiRequest >> HttpRequest) std::string URI(std::string(apiURI_).append("/").append(request.getPath())); internal::HttpRequest httpRequest(URI, request); httpRequest.with(FRED_PARAM_API_KEY, apiKey_); if (!apiFileType_.empty()) { httpRequest.with(FRED_PARAM_FILE_TYPE, apiFileType_); } FREDCPP_LOG_DEBUG("http-request:" << httpRequest); // execute request internal::HttpResponse httpResponse; executor_->execute(httpRequest, httpResponse); if (!httpResponse.isXmlContent()) { response.setError( ErrorHttpRequestFailed(request, httpRequest, httpResponse) ); FREDCPP_LOG_ERROR( response.error.message); return (response.good()); } // process response //std::ofstream os("fred_dbg.bin",std::ifstream::binary); //os << httpResponse.getContentStream().str(); std::istringstream xmlContent(httpResponse.getContentStream().str()); FREDCPP_LOG_DEBUG("http-response:" << httpResponse.getHttpStatus() << " " << "content-type:" << httpResponse.getContentType()); FREDCPP_LOG_DBGN(2, "content:{\n" << xmlContent.str() << "\n}"); if ( !parser_->parse(xmlContent, response) ) { response.setError( ErrorXmlParseFailed(request, xmlContent) ); FREDCPP_LOG_ERROR( response.error.message ); return (response.good()); } response.setErrorFromResult(); //TOADD:FREDCPP_LOG_INFO(response.result, timed) return ( response.good() ); }