in src/Windows/curl_easy.cpp [127:238]
std::unique_ptr<curl_easy> curl_easy::create(
const std::string& url,
const std::string* const p_body,
unsigned long dwFlags)
{
struct make_unique_enabler : public curl_easy
{
};
std::unique_ptr<curl_easy> curl = std::make_unique<make_unique_enabler>();
curl->sessionHandle.reset(WinHttpOpen(
nullptr,
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS,
0));
if (!curl->sessionHandle)
{
throw_on_error(GetLastError(), "curl_easy::create/WinHttpOpen");
}
URL_COMPONENTSW urlComponents = {0};
// Allocate some buffers to hold the various pieces of the URL.
auto urlLen(url.size() + 1);
auto schemeBuffer(std::make_unique<wchar_t[]>(urlLen));
auto hostBuffer(std::make_unique<wchar_t[]>(urlLen));
auto urlBuffer(std::make_unique<wchar_t[]>(urlLen));
auto extraBuffer(std::make_unique<wchar_t[]>(urlLen));
// Set required component lengths to non-zero
// so that they are cracked.
urlComponents.dwStructSize = sizeof(URL_COMPONENTS);
urlComponents.dwSchemeLength = (DWORD)-1;
urlComponents.lpszScheme = schemeBuffer.get();
urlComponents.dwHostNameLength = (DWORD)-1;
urlComponents.lpszHostName = hostBuffer.get();
urlComponents.dwUrlPathLength = (DWORD)-1;
urlComponents.lpszUrlPath = urlBuffer.get();
urlComponents.dwExtraInfoLength = (DWORD)-1;
urlComponents.lpszExtraInfo = extraBuffer.get();
if (!WinHttpCrackUrl(
UnicodeStringFromUtf8String(url).c_str(),
0,
ICU_REJECT_USERPWD,
&urlComponents))
{
throw_on_error(GetLastError(), "curl_easy::create/WinHttpCrackUrl");
}
curl->connectionHandle.reset(WinHttpConnect(
curl->sessionHandle.get(),
urlComponents.lpszHostName,
urlComponents.nPort,
0));
if (!curl->connectionHandle)
{
throw_on_error(GetLastError(), "curl_easy::create/WinHttpConnect");
}
std::wstring urlToRetrieve(urlComponents.lpszUrlPath);
urlToRetrieve += urlComponents.lpszExtraInfo;
curl->request.reset(WinHttpOpenRequest(
curl->connectionHandle.get(),
L"GET",
urlToRetrieve.c_str(),
nullptr,
WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
dwFlags));
if (!curl->request)
{
throw_on_error(GetLastError(), "curl_easy::create/WinHttpOpenRequest");
}
// Enable following redirects on this request.
DWORD redirectPolicy = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
if (!WinHttpSetOption(
curl->request.get(),
WINHTTP_OPTION_REDIRECT_POLICY,
&redirectPolicy,
sizeof(redirectPolicy)))
{
throw_on_error(
GetLastError(),
"curl_easy::create/WinHttpSetOption(RedirectPolicy)");
}
// Specify TLS 1.2
DWORD protocolOptions =
WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 | WINHTTP_FLAG_SECURE_PROTOCOL_SSL3;
if (!WinHttpSetOption(
curl->sessionHandle.get(),
WINHTTP_OPTION_SECURE_PROTOCOLS,
&protocolOptions,
sizeof(protocolOptions)))
{
throw_on_error(
GetLastError(),
"curl_easy::create/WinHttpSetOption(SecureProtocols)");
}
if (p_body != nullptr)
{
curl->request_body_data = *p_body;
}
return std::move(curl);
}