in Source/HTTP/WinHttp/winhttp_connection.cpp [142:287]
HRESULT WinHttpConnection::Initialize()
{
try
{
const char* url = nullptr;
const char* method = nullptr;
RETURN_IF_FAILED(HCHttpCallRequestGetUrl(m_call, &method, &url));
m_uri = Uri{ url };
unsigned int port = m_uri.IsPortDefault() ? (m_uri.IsSecure() ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT) : m_uri.Port();
http_internal_wstring wUrlHost = utf16_from_utf8(m_uri.Host());
m_hConnection = WinHttpConnect(
m_hSession,
wUrlHost.c_str(),
(INTERNET_PORT)port,
0);
if (m_hConnection == nullptr)
{
DWORD dwError = GetLastError();
HC_TRACE_ERROR(HTTPCLIENT, "WinHttpConnection [ID %llu] [TID %ul] WinHttpConnect errorcode %d", TO_ULL(HCHttpCallGetId(m_call)), GetCurrentThreadId(), dwError);
return HRESULT_FROM_WIN32(dwError);
}
// Need to form uri path, query, and fragment for this request.
http_internal_wstring wEncodedResource = utf16_from_utf8(m_uri.Resource());
http_internal_wstring wMethod = utf16_from_utf8(method);
// Open the request.
m_hRequest = WinHttpOpenRequest(
m_hConnection,
wMethod.c_str(),
wEncodedResource.c_str(),
nullptr,
WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
WINHTTP_FLAG_ESCAPE_DISABLE | (m_uri.IsSecure() ? WINHTTP_FLAG_SECURE : 0));
if (m_hRequest == nullptr)
{
DWORD dwError = GetLastError();
HC_TRACE_ERROR(HTTPCLIENT, "WinHttpConnection [ID %llu] [TID %ul] WinHttpOpenRequest errorcode %d", TO_ULL(HCHttpCallGetId(m_call)), GetCurrentThreadId(), dwError);
return HRESULT_FROM_WIN32(dwError);
}
uint32_t timeoutInSeconds = 0;
RETURN_IF_FAILED(HCHttpCallRequestGetTimeout(m_call, &timeoutInSeconds));
int timeoutInMilliseconds = static_cast<int>(timeoutInSeconds * 1000);
if (!WinHttpSetTimeouts(
m_hSession,
timeoutInMilliseconds,
timeoutInMilliseconds,
timeoutInMilliseconds,
timeoutInMilliseconds))
{
DWORD dwError = GetLastError();
HC_TRACE_ERROR(HTTPCLIENT, "WinHttpConnection [ID %llu] [TID %ul] WinHttpSetTimeouts errorcode %d", TO_ULL(HCHttpCallGetId(m_call)), GetCurrentThreadId(), dwError);
return HRESULT_FROM_WIN32(dwError);
}
#if HC_PLATFORM_IS_MICROSOFT && (HC_PLATFORM != HC_PLATFORM_UWP) && (HC_PLATFORM != HC_PLATFORM_XDK)
if (!m_call->sslValidation)
{
DWORD dwOption = SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
if (!WinHttpSetOption(
m_hRequest,
WINHTTP_OPTION_SECURITY_FLAGS,
&dwOption,
sizeof(dwOption)))
{
DWORD dwError = GetLastError();
HC_TRACE_WARNING(HTTPCLIENT, "WinHttpConnection [ID %llu] [TID %ul] WinHttpSetOption errorcode %d", HCHttpCallGetId(m_call), GetCurrentThreadId(), dwError);
}
}
#endif
#if HC_PLATFORM != HC_PLATFORM_GDK
if (m_proxyType == proxy_type::autodiscover_proxy)
{
RETURN_IF_FAILED(set_autodiscover_proxy());
}
#endif
HCHttpCallRequestBodyReadFunction requestBodyReadFunction{ nullptr };
void* context{ nullptr };
RETURN_IF_FAILED(HCHttpCallRequestGetRequestBodyReadFunction(m_call, &requestBodyReadFunction, &m_requestBodySize, &context));
if (m_requestBodySize > 0)
{
// While we won't be transfer-encoding the data, we will write it in portions.
m_requestBodyType = msg_body_type::content_length_chunked;
m_requestBodyRemainingToWrite = m_requestBodySize;
}
else
{
m_requestBodyType = msg_body_type::no_body;
m_requestBodyRemainingToWrite = 0;
}
uint32_t numHeaders = 0;
RETURN_IF_FAILED(HCHttpCallRequestGetNumHeaders(m_call, &numHeaders));
if (numHeaders > 0)
{
http_internal_wstring flattenedHeaders = flatten_http_headers(m_call->requestHeaders);
if (!WinHttpAddRequestHeaders(
m_hRequest,
flattenedHeaders.c_str(),
static_cast<DWORD>(flattenedHeaders.length()),
WINHTTP_ADDREQ_FLAG_ADD))
{
DWORD dwError = GetLastError();
HC_TRACE_ERROR(HTTPCLIENT, "WinHttpConnection [ID %llu] [TID %ul] WinHttpAddRequestHeaders errorcode %d", TO_ULL(HCHttpCallGetId(m_call)), GetCurrentThreadId(), dwError);
return HRESULT_FROM_WIN32(dwError);
}
}
if (m_uri.IsSecure())
{
if (!WinHttpSetOption(
m_hRequest,
WINHTTP_OPTION_CLIENT_CERT_CONTEXT,
WINHTTP_NO_CLIENT_CERT_CONTEXT,
0))
{
DWORD dwError = GetLastError();
HC_TRACE_ERROR(HTTPCLIENT, "WinHttpConnection [ID %llu] [TID %ul] WinHttpSetOption errorcode %d", TO_ULL(HCHttpCallGetId(m_call)), GetCurrentThreadId(), dwError);
return HRESULT_FROM_WIN32(dwError);
}
}
}
catch (std::bad_alloc const& e)
{
HC_TRACE_ERROR(HTTPCLIENT, "WinHttpConnection [%d] std::bad_alloc: %s", E_OUTOFMEMORY, e.what());
return E_OUTOFMEMORY;
}
catch (...)
{
HC_TRACE_ERROR(HTTPCLIENT, "WinHttpConnection [%d] unknown exception", E_FAIL);
return E_FAIL;
}
return S_OK;
}