in Source/HTTP/XMLHttp/xmlhttp_http_task.cpp [50:207]
void xmlhttp_http_task::perform_async(
_Inout_ XAsyncBlock* asyncBlock,
_In_ HCCallHandle call
)
{
try
{
const char* url = nullptr;
const char* method = nullptr;
HCHttpCallRequestBodyReadFunction requestBodyReadFunction = nullptr;
size_t requestBodySize = 0;
void* context = nullptr;
HCHttpCallRequestGetUrl(call, &method, &url);
HCHttpCallRequestGetRequestBodyReadFunction(call, &requestBodyReadFunction, &requestBodySize, &context);
uint32_t numHeaders = 0;
HCHttpCallRequestGetNumHeaders(call, &numHeaders);
uint32_t timeoutInSeconds = 0;
HCHttpCallRequestGetTimeout(call, &timeoutInSeconds);
HRESULT hr = CoCreateInstance(
__uuidof(FreeThreadedXMLHTTP60),
nullptr,
#if HC_XDK_API
CLSCTX_SERVER,
#else
CLSCTX_INPROC,
#endif
__uuidof(IXMLHTTPRequest2),
reinterpret_cast<void**>(m_hRequest.GetAddressOf()));
if (FAILED(hr))
{
HC_TRACE_ERROR(HTTPCLIENT, "Failure to create IXMLHTTPRequest2 instance 0x%0.8x", hr);
HCHttpCallResponseSetNetworkErrorCode(call, hr, hr);
XAsyncComplete(asyncBlock, S_OK, 0);
return;
}
std::shared_ptr<hc_task> httpTask2 = shared_from_this();
std::shared_ptr<xmlhttp_http_task> httpTask = std::dynamic_pointer_cast<xmlhttp_http_task>(httpTask2);
http_internal_wstring wMethod = utf16_from_utf8(method);
http_internal_wstring wUrl = utf16_from_utf8(url);
hr = m_hRequest->Open(
wMethod.c_str(),
wUrl.c_str(),
Microsoft::WRL::Make<http_request_callback>(httpTask).Get(),
nullptr,
nullptr,
nullptr,
nullptr);
if (FAILED(hr))
{
HC_TRACE_ERROR(HTTPCLIENT, "Failure to open HTTP request 0x%0.8x", hr);
HCHttpCallResponseSetNetworkErrorCode(call, hr, hr);
XAsyncComplete(asyncBlock, S_OK, 0);
return;
}
m_hRequest->SetProperty(XHR_PROP_NO_CRED_PROMPT, TRUE);
ULONGLONG timeout = static_cast<ULONGLONG>(timeoutInSeconds * 1000);
m_hRequest->SetProperty(XHR_PROP_TIMEOUT, timeout);
#ifdef XHR_PROP_ONDATA_NEVER
m_hRequest->SetProperty(XHR_PROP_ONDATA_THRESHOLD, XHR_PROP_ONDATA_NEVER);
#endif
bool userAgentSet = false;
for (uint32_t i = 0; i < numHeaders; i++)
{
const char* iHeaderName;
const char* iHeaderValue;
HCHttpCallRequestGetHeaderAtIndex(call, i, &iHeaderName, &iHeaderValue);
if (iHeaderName != nullptr && iHeaderValue != nullptr)
{
if (xbox::httpclient::str_icmp(iHeaderName, "User-Agent") == 0)
{
userAgentSet = true;
}
hr = m_hRequest->SetRequestHeader(utf16_from_utf8(iHeaderName).c_str(), utf16_from_utf8(iHeaderValue).c_str());
}
}
if (!userAgentSet)
{
m_hRequest->SetRequestHeader(L"User-Agent", L"libHttpClient/1.0.0.0");
}
hr = m_hRequest->SetCustomResponseStream(Microsoft::WRL::Make<http_response_stream>(httpTask).Get());
if (FAILED(hr))
{
HC_TRACE_ERROR(HTTPCLIENT, "Failure to set HTTP response stream 0x%0.8x", hr);
HCHttpCallResponseSetNetworkErrorCode(call, hr, hr);
XAsyncComplete(asyncBlock, S_OK, 0);
return;
}
if (requestBodySize > 0 && requestBodyReadFunction != nullptr)
{
auto requestStream = Microsoft::WRL::Make<http_request_stream>();
if (requestStream != nullptr)
{
hr = requestStream->init(call);
}
else
{
hr = E_OUTOFMEMORY;
}
if (FAILED(hr))
{
HC_TRACE_ERROR(HTTPCLIENT, "[%d] http_request_stream failed in xmlhttp_http_task.", hr);
HCHttpCallResponseSetNetworkErrorCode(call, E_FAIL, static_cast<uint32_t>(hr));
XAsyncComplete(asyncBlock, S_OK, 0);
return;
}
hr = m_hRequest->Send(requestStream.Get(), requestBodySize);
}
else
{
hr = m_hRequest->Send(nullptr, 0);
}
if (FAILED(hr))
{
HC_TRACE_ERROR(HTTPCLIENT, "Failure to send HTTP request 0x%0.8x", hr);
HCHttpCallResponseSetNetworkErrorCode(call, hr, hr);
XAsyncComplete(asyncBlock, S_OK, 0);
return;
}
// If there were no errors so far, HCTaskSetCompleted is called later
// http_request_callback::OnResponseReceived
// or
// http_request_callback::OnError
}
catch (std::bad_alloc const& e)
{
HC_TRACE_ERROR(HTTPCLIENT, "[%d] std::bad_alloc in xmlhttp_http_task: %s", E_OUTOFMEMORY, e.what());
HCHttpCallResponseSetNetworkErrorCode(call, E_OUTOFMEMORY, static_cast<uint32_t>(E_OUTOFMEMORY));
XAsyncComplete(asyncBlock, E_OUTOFMEMORY, 0);
}
catch (std::exception const& e)
{
HC_TRACE_ERROR(HTTPCLIENT, "[%d] std::exception in xmlhttp_http_task: %s", E_FAIL, e.what());
HCHttpCallResponseSetNetworkErrorCode(call, E_FAIL, static_cast<uint32_t>(E_FAIL));
XAsyncComplete(asyncBlock, E_FAIL, 0);
}
catch (...)
{
HC_TRACE_ERROR(HTTPCLIENT, "[%d] unknown exception in xmlhttp_http_task", E_FAIL);
HCHttpCallResponseSetNetworkErrorCode(call, E_FAIL, static_cast<uint32_t>(E_FAIL));
XAsyncComplete(asyncBlock, E_FAIL, 0);
}
}