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); }
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)); }