<commit_before>﻿// Copyright (c) Microsoft Corporation
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include "pch.h"
#include "xsapi/xbox_live_context_settings.h"
#include "xbox_service_call_routed_event_args_internal.h"
#include "http_call_response_internal.h"
#include "user_context.h"
#include "utils.h"
#include "telemetry.h"
#ifdef _WIN32
#include "service_call_logger_data.h"
#include "service_call_logger.h"
#endif
#include "http_call_impl.h"

NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_BEGIN

const int RETRY_AFTER_CAP = 15;

http_call_response::http_call_response(
    _In_ std::shared_ptr<http_call_response_internal> internalObj
    ) :
    m_internalObj(std::move(internalObj))
{
}

std::shared_ptr<http_call_response_internal> http_call_response::_Internal_response() const
{
    return m_internalObj;
}

web::http::http_headers http_call_response::response_headers() const
{
    auto headers = web::http::http_headers();

    auto& internalHeaders = m_internalObj->response_headers();
    for (auto& kvp : internalHeaders)
    {
        headers.add(utils::string_t_from_internal_string(kvp.first), utils::string_t_from_internal_string(kvp.second));
    }
    return headers;
}

DEFINE_GET_ENUM_TYPE(http_call_response, http_call_response_body_type, body_type);
DEFINE_GET_STRING(http_call_response, response_body_string);
DEFINE_GET_OBJECT_REF(http_call_response, web::json::value, response_body_json);
DEFINE_GET_VECTOR(http_call_response, unsigned char, response_body_vector);
DEFINE_GET_UINT32(http_call_response, http_status);
DEFINE_GET_OBJECT_REF(http_call_response, std::error_code, err_code);
DEFINE_GET_STD_STRING(http_call_response, err_message);
DEFINE_GET_STRING(http_call_response, e_tag);
DEFINE_GET_STRING(http_call_response, response_date);
DEFINE_GET_OBJECT_REF(http_call_response, std::chrono::seconds, retry_after);

http_call_response_internal::http_call_response_internal(
    _In_ const xsapi_internal_string& xboxUserId,
    _In_ const std::shared_ptr<xbox_live_context_settings>& xboxLiveContextSettings,
    _In_ const xsapi_internal_string& httpMethod,
    _In_ const xsapi_internal_string& fullUrl,
    _In_ const http_call_request_message_internal& requestBody,
    _In_ xbox_live_api xboxLiveApi,
    _In_ uint32_t responseStatusCode
    ) :
    m_httpCallResponseBodyType(http_call_response_body_type::string_body),
    m_xboxUserId(xboxUserId),
    m_xboxLiveContextSettings(xboxLiveContextSettings),
    m_httpMethod(httpMethod),
    m_fullUrl(fullUrl),
    m_xboxLiveApi(xboxLiveApi),
    m_requestBody(requestBody),
    m_httpStatus(responseStatusCode)
{
}

http_call_response_internal::http_call_response_internal(
    _In_ const std::shared_ptr<http_call_data> httpCallData
    )
{
    HRESULT hr = S_OK;
    uint32_t platformErrorCode = 0;
    HCHttpCallResponseGetNetworkErrorCode(httpCallData->callHandle, &hr, &platformErrorCode);
    HCHttpCallResponseGetStatusCode(httpCallData->callHandle, &m_httpStatus);
    
    // SHIPTODO check if response should be binary and not string
    PCSTR responseBody = nullptr;
    HCHttpCallResponseGetResponseString(httpCallData->callHandle, &responseBody);

    if (httpCallData->userContext != nullptr)
    {
        m_xboxUserId = httpCallData->userContext->xbox_user_id();
    }
    m_xboxLiveContextSettings = httpCallData->xboxLiveContextSettings;
    m_httpMethod = httpCallData->httpMethod;
    m_fullUrl = httpCallData->serverName + utils::internal_string_from_string_t(httpCallData->pathQueryFragment.to_string());
    m_requestBody = httpCallData->requestBody;
    m_xboxLiveApi = httpCallData->xboxLiveApi;
    m_requestTime = httpCallData->requestStartTime;
    m_responseTime = chrono_clock_t::now();

    uint32_t numHeaders;
    HCHttpCallResponseGetNumHeaders(httpCallData->callHandle, &numHeaders);
    for (uint32_t i = 0; i < numHeaders; ++i)
    {
        UTF8CSTR headerName;
        UTF8CSTR headerValue;
        HCHttpCallResponseGetHeaderAtIndex(httpCallData->callHandle, i, &headerName, &headerValue);
        m_responseHeaders[headerName] = headerValue;
    }

    if (FAILED(hr))
    {
        xsapi_internal_string errMessage;
        m_errorCode = static_cast<xbox_live_error_code>(hr);
        if (responseBody != nullptr)
        {
            m_errorMessage = " HTTP Response Body: " + xsapi_internal_string(responseBody);
        }
    }
    else
    {
#pragma warning(suppress: 4244)
        m_errorCode = get_xbox_live_error_code_from_http_status(m_httpStatus);

        web::json::value responseBodyJson;
        std::error_code errCode;
        switch (httpCallData->httpCallResponseBodyType)
        {<commit_msg>Added response header using the helper function (#405)<commit_after>﻿// Copyright (c) Microsoft Corporation
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include "pch.h"
#include "xsapi/xbox_live_context_settings.h"
#include "xbox_service_call_routed_event_args_internal.h"
#include "http_call_response_internal.h"
#include "user_context.h"
#include "utils.h"
#include "telemetry.h"
#ifdef _WIN32
#include "service_call_logger_data.h"
#include "service_call_logger.h"
#endif
#include "http_call_impl.h"

NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_BEGIN

const int RETRY_AFTER_CAP = 15;

http_call_response::http_call_response(
    _In_ std::shared_ptr<http_call_response_internal> internalObj
    ) :
    m_internalObj(std::move(internalObj))
{
}

std::shared_ptr<http_call_response_internal> http_call_response::_Internal_response() const
{
    return m_internalObj;
}

web::http::http_headers http_call_response::response_headers() const
{
    auto headers = web::http::http_headers();

    auto& internalHeaders = m_internalObj->response_headers();
    for (auto& kvp : internalHeaders)
    {
        headers.add(utils::string_t_from_internal_string(kvp.first), utils::string_t_from_internal_string(kvp.second));
    }
    return headers;
}

DEFINE_GET_ENUM_TYPE(http_call_response, http_call_response_body_type, body_type);
DEFINE_GET_STRING(http_call_response, response_body_string);
DEFINE_GET_OBJECT_REF(http_call_response, web::json::value, response_body_json);
DEFINE_GET_VECTOR(http_call_response, unsigned char, response_body_vector);
DEFINE_GET_UINT32(http_call_response, http_status);
DEFINE_GET_OBJECT_REF(http_call_response, std::error_code, err_code);
DEFINE_GET_STD_STRING(http_call_response, err_message);
DEFINE_GET_STRING(http_call_response, e_tag);
DEFINE_GET_STRING(http_call_response, response_date);
DEFINE_GET_OBJECT_REF(http_call_response, std::chrono::seconds, retry_after);

http_call_response_internal::http_call_response_internal(
    _In_ const xsapi_internal_string& xboxUserId,
    _In_ const std::shared_ptr<xbox_live_context_settings>& xboxLiveContextSettings,
    _In_ const xsapi_internal_string& httpMethod,
    _In_ const xsapi_internal_string& fullUrl,
    _In_ const http_call_request_message_internal& requestBody,
    _In_ xbox_live_api xboxLiveApi,
    _In_ uint32_t responseStatusCode
    ) :
    m_httpCallResponseBodyType(http_call_response_body_type::string_body),
    m_xboxUserId(xboxUserId),
    m_xboxLiveContextSettings(xboxLiveContextSettings),
    m_httpMethod(httpMethod),
    m_fullUrl(fullUrl),
    m_xboxLiveApi(xboxLiveApi),
    m_requestBody(requestBody),
    m_httpStatus(responseStatusCode)
{
}

http_call_response_internal::http_call_response_internal(
    _In_ const std::shared_ptr<http_call_data> httpCallData
    )
{
    HRESULT hr = S_OK;
    uint32_t platformErrorCode = 0;
    HCHttpCallResponseGetNetworkErrorCode(httpCallData->callHandle, &hr, &platformErrorCode);
    HCHttpCallResponseGetStatusCode(httpCallData->callHandle, &m_httpStatus);
    
    // SHIPTODO check if response should be binary and not string
    PCSTR responseBody = nullptr;
    HCHttpCallResponseGetResponseString(httpCallData->callHandle, &responseBody);

    if (httpCallData->userContext != nullptr)
    {
        m_xboxUserId = httpCallData->userContext->xbox_user_id();
    }
    m_xboxLiveContextSettings = httpCallData->xboxLiveContextSettings;
    m_httpMethod = httpCallData->httpMethod;
    m_fullUrl = httpCallData->serverName + utils::internal_string_from_string_t(httpCallData->pathQueryFragment.to_string());
    m_requestBody = httpCallData->requestBody;
    m_xboxLiveApi = httpCallData->xboxLiveApi;
    m_requestTime = httpCallData->requestStartTime;
    m_responseTime = chrono_clock_t::now();

    uint32_t numHeaders;
    HCHttpCallResponseGetNumHeaders(httpCallData->callHandle, &numHeaders);
    for (uint32_t i = 0; i < numHeaders; ++i)
    {
        UTF8CSTR headerName;
        UTF8CSTR headerValue;
        HCHttpCallResponseGetHeaderAtIndex(httpCallData->callHandle, i, &headerName, &headerValue);
        add_response_header(headerName, headerValue);
    }

    if (FAILED(hr))
    {
        xsapi_internal_string errMessage;
        m_errorCode = static_cast<xbox_live_error_code>(hr);
        if (responseBody != nullptr)
        {
            m_errorMessage = " HTTP Response Body: " + xsapi_internal_string(responseBody);
        }
    }
    else
    {
#pragma warning(suppress: 4244)
        m_errorCode = get_xbox_live_error_code_from_http_status(m_httpStatus);

        web::json::value responseBodyJson;
        std::error_code errCode;
        switch (httpCallData->httpCallResponseBodyType)
        {
{'fraction_non_alphanumeric': 0.08785502331496396, 'fraction_numerical': 0.004980924120389996, 'mean_word_length': 5.631763879128601, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4921136', 'n_tokens_mistral': 3133, 'n_tokens_neox': 3082, 'n_words': 477}