CURLcode HttpClient::set_curl_http_options()

in host/AzureRecoveryLib/resthelper/HttpClient.cpp [703:892]


CURLcode HttpClient::set_curl_http_options(const HttpRequest& request, HttpResponse & response, curl_slist* headers)
{
    TRACE_FUNC_BEGIN;
    CURLcode curl_err = CURLE_OK;

    if (NULL == m_curl && !reset_curl_handle())
    {
        TRACE_ERROR("Curl inititialization error.\n");
        return CURLE_FAILED_INIT;
    }

    do {

        {
            // override the http_proxy/https_proxy env variables if custom proxy is specified
            if (!m_proxy.GetAddress().empty())
            {
                TRACE_INFO("Setting curl option proxy as %s\n", m_proxy.GetAddress().c_str());
                curl_err = curl_easy_setopt(m_curl, CURLOPT_PROXY, m_proxy.GetAddress().c_str());
                if (CURLE_OK != curl_err) break;
            }
            // override no_proxy env variable
            if (!m_proxy.GetBypassList().empty())
            {
                TRACE_INFO("Setting curl option no_proxy as %s\n", m_proxy.GetBypassList().c_str());
                curl_err = curl_easy_setopt(m_curl, CURLOPT_NOPROXY, m_proxy.GetBypassList().c_str());
                if (CURLE_OK != curl_err) break;
            }
        }

        // Curl verbose info options
        if (s_verbose)
        {
            curl_err = curl_easy_setopt(m_curl, CURLOPT_VERBOSE, 1L);
            if (CURLE_OK != curl_err) break;

            curl_err = curl_easy_setopt(m_curl, CURLOPT_DEBUGFUNCTION, &HttpClient::debug_callback);
            if (CURLE_OK != curl_err) break;

            /*curl_err = curl_easy_setopt(m_curl, CURLOPT_DEBUGDATA, NULL);
            if (CURLE_OK != curl_err) break;*/
        }

        memset(m_errorbuff, 0, ARRAYSIZE(m_errorbuff));
        curl_err = curl_easy_setopt(m_curl, CURLOPT_ERRORBUFFER, m_errorbuff);
        if (CURLE_OK != curl_err) break;

        curl_err = curl_easy_setopt(m_curl, CURLOPT_NOSIGNAL, 1L);
        if (CURLE_OK != curl_err) break;
        curl_err = curl_easy_setopt(m_curl, CURLOPT_TCP_NODELAY, 1L);
        if (CURLE_OK != curl_err) break;

        curl_err = curl_easy_setopt(m_curl, CURLOPT_TIMEOUT, request.m_timeout);
        if (CURLE_OK != curl_err) break;

        if (m_presentClientCert)
        {
            boost::filesystem::path keyFilePath(securitylib::getPrivateDir());
            keyFilePath /= securitylib::CLIENT_CERT_NAME + securitylib::EXTENSION_KEY;
            boost::filesystem::path certFilePath(securitylib::getCertDir());
            certFilePath /= securitylib::CLIENT_CERT_NAME + securitylib::EXTENSION_CRT;

            curl_err = curl_easy_setopt(m_curl, CURLOPT_SSLCERT, certFilePath.string().c_str());
            if (CURLE_OK != curl_err) break;
            curl_err = curl_easy_setopt(m_curl, CURLOPT_SSLKEY, keyFilePath.string().c_str());
            if (CURLE_OK != curl_err) break;
            curl_err = curl_easy_setopt(m_curl, CURLOPT_KEYPASSWD, "");
            if (CURLE_OK != curl_err) break;
        }

        if (m_enableSSLAuthentication) 
        {
            /*curl_err = curl_easy_setopt(m_curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_MAX_TLSv1_2);
            if (CURLE_OK != curl_err) break;*/

            // Enable Server Certificate validation
            curl_err = curl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYPEER, 1L);
            if (CURLE_OK != curl_err) break;

            curl_err = curl_easy_setopt(m_curl, CURLOPT_CERTINFO, 1L);
            if (CURLE_OK != curl_err) break;

            if (m_allowSelfSignedCertVerification)
            {
                curl_err = curl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYHOST, 0L);
                if (CURLE_OK != curl_err) break;

                curl_err = curl_easy_setopt(m_curl, CURLOPT_SSL_CTX_DATA, (void*)&response);
                if (CURLE_OK != curl_err) break;

                curl_err = curl_easy_setopt(m_curl, CURLOPT_SSL_CTX_FUNCTION, &HttpClient::ssl_ctx_callback_for_self_signed);
                if (CURLE_OK != curl_err) break;
            }
            else
            {
#ifdef WIN32
                curl_err = curl_easy_setopt(m_curl, CURLOPT_SSL_CTX_DATA, (void *)this);
                if (CURLE_OK != curl_err) break;

                curl_err = curl_easy_setopt(m_curl, CURLOPT_SSL_CTX_FUNCTION, &HttpClient::ssl_ctx_callback);
                if (CURLE_OK != curl_err) break;
#endif
            }
        }
        else
        {
            TRACE("Server cert validation disabled\n");

            // Disable Server Certificate validation
            curl_err = curl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYPEER, 0L);
            if (CURLE_OK != curl_err) break;

            curl_err = curl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYHOST, 0L);
            if (CURLE_OK != curl_err) break;

            curl_err = curl_easy_setopt(m_curl, CURLOPT_CERTINFO, 1L);
            if (CURLE_OK != curl_err) break;
        }
        
        // Response header handling options
        curl_err = curl_easy_setopt(m_curl, CURLOPT_WRITEHEADER, &response);
        if (CURLE_OK != curl_err) break;
        curl_err = curl_easy_setopt(m_curl, CURLOPT_HEADERFUNCTION, &HttpClient::header_data_callback);
        if (CURLE_OK != curl_err) break;

        // Response body handling
        curl_err = curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, &HttpClient::write_data_callback);
        if (CURLE_OK != curl_err) break;
        curl_err = curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &response);
        if (CURLE_OK != curl_err) break;

        // Set Request headers
        if (NULL != headers)
        {
            if (HTTP_POST == request.m_req_method)
                headers = curl_slist_append(headers, "Expect: 100-continue");
            curl_err = curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, headers);
            if (CURLE_OK != curl_err) break;
        }
            
        // Set Http Method specific options
        if (HTTP_PUT == request.m_req_method)
        {
            curl_err = curl_easy_setopt(m_curl, CURLOPT_UPLOAD, 1L);
            if (CURLE_OK != curl_err) break;
            curl_err = curl_easy_setopt(m_curl, CURLOPT_READDATA, &request);
            if (CURLE_OK != curl_err) break;
            curl_err = curl_easy_setopt(m_curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)request.m_request_stream.cb_buff_length);
            if (CURLE_OK != curl_err) break;
            curl_err = curl_easy_setopt(m_curl, CURLOPT_READFUNCTION, &HttpClient::read_data_callback);
            if (CURLE_OK != curl_err) break;
        }
        else if (HTTP_DELETE == request.m_req_method ||
                    HTTP_HEAD == request.m_req_method)
        {
            curl_err = curl_easy_setopt(m_curl, CURLOPT_NOBODY, 1L);
            if (CURLE_OK != curl_err) break;
        }
        else if (HTTP_POST == request.m_req_method)
        {
            curl_err = curl_easy_setopt(m_curl, CURLOPT_POSTFIELDS, request.m_request_stream.buffer);
            if (CURLE_OK != curl_err) break;
            curl_err = curl_easy_setopt(m_curl, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)request.m_request_stream.cb_buff_length);
            if (CURLE_OK != curl_err) break;
        }
        else if (HTTP_GET == request.m_req_method)
        {
            //No specific options.
        }
        else
        {
            TRACE_ERROR("Unkown http method specified.\n");
            curl_err = CURLE_UNKNOWN_OPTION;
            break;
        }

        curl_err = curl_easy_setopt(m_curl, CURLOPT_CUSTOMREQUEST, request.GetHttpMethodStr().c_str());
        if (CURLE_OK != curl_err) break;

        curl_err = curl_easy_setopt(m_curl, CURLOPT_URL, request.m_res_absolute_url.c_str());
        if (CURLE_OK != curl_err) break;

    } while (false);

    if (CURLE_OK != curl_err)
        TRACE_ERROR("Error in setting curl options. Error (%d) %s\n", curl_err, curl_easy_strerror(curl_err));

    TRACE_FUNC_END;
    return curl_err;
}