void WinHttpSyncHttpClient::DoAddHeaders(void* hHttpRequest, Aws::String& headerStr) const
{

    Aws::WString wHeaderString = StringUtils::ToWString(headerStr.c_str());

    WinHttpAddRequestHeaders(hHttpRequest, wHeaderString.c_str(), (DWORD)wHeaderString.length(), WINHTTP_ADDREQ_FLAG_REPLACE | WINHTTP_ADDREQ_FLAG_ADD);
}
Exemple #2
0
Aws::WString StringUtils::ToWString(const char* source)
{
    Aws::WString outString;

    outString.resize(std::strlen(source));
    std::copy(source, source + std::strlen(source), outString.begin());
    return outString;
}
void WinHttpSyncHttpClient::DoAddHeaders(void* hHttpRequest, Aws::String& headerStr) const
{

    Aws::WString wHeaderString = StringUtils::ToWString(headerStr.c_str());

    if (!WinHttpAddRequestHeaders(hHttpRequest, wHeaderString.c_str(), (DWORD)wHeaderString.length(), WINHTTP_ADDREQ_FLAG_REPLACE | WINHTTP_ADDREQ_FLAG_ADD))
        AWS_LOGSTREAM_ERROR(GetLogTag(), "Failed to add HTTP request headers with error code: " << GetLastError());
}
/**
 * See
 * https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
 * to understand how could we pass long path (over 260 chars) to WinAPI
 */
static inline Aws::WString ToLongPath(const Aws::WString& path)
{
    if (path.size() > MAX_PATH - 12/*8.3 file name*/)
    {
        return L"\\\\?\\" + path;
    }
    return path;
}
TEST(StringUtilsTest, TestStringNonAsciiToWString)
{
    AWS_BEGIN_MEMORY_TEST(16, 10)

    Aws::String startString;

    const char startVal = 115;
    
    const char incrementVal = 10;
    const char loopCount = 10;
    for (char i = 0; i < loopCount; ++i)
    {
        startString.push_back(static_cast<char>(startVal + incrementVal * i));
    }

    Aws::WString outString = StringUtils::ToWString(startString.c_str());
    ASSERT_EQ(outString.length(), loopCount);

    AWS_END_MEMORY_TEST
}
TEST(StringUtilsTest, TestWStringNonAsciiToString)
{
    AWS_BEGIN_MEMORY_TEST(16, 10)

    Aws::WString startString;

    // Toss in a couple ascii characters to start, then go over 127
    const char startVal = 115;
    int addValue = startVal;
    const char incrementVal = 10;
    const char loopCount = 10;
    for (char i = 0; i < loopCount; ++i)
    {
        startString.push_back(static_cast<wchar_t>(addValue));
        addValue += incrementVal;
    }

    Aws::String outString = StringUtils::FromWString(startString.c_str());
    ASSERT_EQ(outString.length(), loopCount);

    for (size_t i = 0; i < outString.length(); ++i)
    {
        char testValue = outString[i];
        ASSERT_EQ(testValue, static_cast<char>(startVal + incrementVal * i));
    }

    // This loop will cross the byte limit
    for (char i = 0; i < loopCount; ++i)
    {
        startString.push_back(static_cast<wchar_t>(addValue));
        addValue += incrementVal;
    }
    // Verify the length, not the values though
    outString = StringUtils::FromWString(startString.c_str());
    ASSERT_EQ(outString.length(), loopCount * 2);

    AWS_END_MEMORY_TEST
}
void* WinHttpSyncHttpClient::OpenRequest(const Aws::Http::HttpRequest& request, void* connection, const Aws::StringStream& ss) const
{

    DWORD requestFlags = WINHTTP_FLAG_REFRESH |
        (request.GetUri().GetScheme() == Scheme::HTTPS ? WINHTTP_FLAG_SECURE : 0);

    static LPCWSTR accept[2] = { L"*/*", nullptr };

    Aws::WString wss = StringUtils::ToWString(ss.str().c_str());

    HINTERNET hHttpRequest = WinHttpOpenRequest(connection, StringUtils::ToWString(HttpMethodMapper::GetNameForHttpMethod(request.GetMethod())).c_str(),
        wss.c_str(), nullptr, nullptr, accept, requestFlags);

    //DISABLE_FEATURE settings need to be made after OpenRequest but before SendRequest
    if (!m_allowRedirects)
    {
        requestFlags = WINHTTP_DISABLE_REDIRECTS;

        if (!WinHttpSetOption(hHttpRequest, WINHTTP_OPTION_DISABLE_FEATURE, &requestFlags, sizeof(requestFlags)))
            AWS_LOG_FATAL(GetLogTag(), "Failed to turn off redirects!");
    }
    return hHttpRequest;
}
WinHttpSyncHttpClient::WinHttpSyncHttpClient(const ClientConfiguration& config) :
    Base()
{
    AWS_LOGSTREAM_INFO(GetLogTag(), "Creating http client with user agent " << config.userAgent << " with max connections " << config.maxConnections 
        << " request timeout " << config.requestTimeoutMs << ",and connect timeout " << config.connectTimeoutMs);

    DWORD winhttpFlags = WINHTTP_ACCESS_TYPE_NO_PROXY;
    const char* proxyHosts = nullptr;
    Aws::String strProxyHosts;

    m_allowRedirects = config.followRedirects;

    bool isUsingProxy = !config.proxyHost.empty();
    //setup initial proxy config.

    Aws::WString proxyString;

    if (isUsingProxy)
    {
        AWS_LOGSTREAM_INFO(GetLogTag(), "Http Client is using a proxy. Setting up proxy with settings host " << config.proxyHost
             << ", port " << config.proxyPort << ", username " << config.proxyUserName);


        winhttpFlags = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
        Aws::StringStream ss;
        const char* schemeString = Aws::Http::SchemeMapper::ToString(config.scheme);
        ss << StringUtils::ToUpper(schemeString) << "=" << schemeString << "://" << config.proxyHost << ":" << config.proxyPort;
        strProxyHosts.assign(ss.str());
        proxyHosts = strProxyHosts.c_str();

        proxyString = StringUtils::ToWString(proxyHosts);
        AWS_LOGSTREAM_DEBUG(GetLogTag(), "Adding proxy host string to winhttp " << proxyHosts);
    }

    Aws::WString openString = StringUtils::ToWString(config.userAgent.c_str());

    SetOpenHandle(WinHttpOpen(openString.c_str(), winhttpFlags, proxyString.c_str(), nullptr, 0));

    if (!WinHttpSetTimeouts(GetOpenHandle(), config.connectTimeoutMs, config.connectTimeoutMs, -1, config.requestTimeoutMs))
    {
        AWS_LOGSTREAM_WARN(GetLogTag(), "Error setting timeouts " << GetLastError());
    }

    //add proxy auth credentials to everything using this handle.
    if (isUsingProxy)
    {
        if (!config.proxyUserName.empty() && !WinHttpSetOption(GetOpenHandle(), WINHTTP_OPTION_PROXY_USERNAME, (LPVOID)config.proxyUserName.c_str(), (DWORD)config.proxyUserName.length()))
            AWS_LOGSTREAM_FATAL(GetLogTag(), "Failed setting username for proxy with error code: " << GetLastError());
        if (!config.proxyPassword.empty() && !WinHttpSetOption(GetOpenHandle(), WINHTTP_OPTION_PROXY_PASSWORD, (LPVOID)config.proxyPassword.c_str(), (DWORD)config.proxyPassword.length()))
            AWS_LOGSTREAM_FATAL(GetLogTag(), "Failed setting password for proxy with error code: " << GetLastError());
    }

    if (!config.verifySSL)
    {
        AWS_LOG_WARN(GetLogTag(), "Turning ssl unknown ca verification off.");
        DWORD flags = SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_CN_INVALID;

        if (!WinHttpSetOption(GetOpenHandle(), WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags)))
            AWS_LOG_FATAL(GetLogTag(), "Failed to turn ssl cert ca verification off.");
    }
    else
    {
        //disable insecure tls protocols, otherwise you might as well turn ssl verification off.
        DWORD flags = WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2;
        if (!WinHttpSetOption(GetOpenHandle(), WINHTTP_OPTION_SECURE_PROTOCOLS, &flags, sizeof(flags)))
        {
            AWS_LOGSTREAM_FATAL(GetLogTag(), "Failed setting secure crypto protocols with error code: " << GetLastError());
        }
    }

    AWS_LOG_DEBUG(GetLogTag(), "API handle %p.", GetOpenHandle());
    SetConnectionPoolManager(Aws::New<WinHttpConnectionPoolMgr>(GetLogTag(),
        GetOpenHandle(), config.maxConnections, config.requestTimeoutMs, config.connectTimeoutMs));
}