123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- /**
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0.
- */
- #include <aws/core/endpoint/DefaultEndpointProvider.h>
- #include <aws/core/utils/memory/stl/AWSMap.h>
- #include <aws/crt/Api.h>
- namespace Aws
- {
- namespace Endpoint
- {
- /**
- * Export endpoint provider symbols from DLL
- */
- template class AWS_CORE_API DefaultEndpointProvider<Aws::Client::GenericClientConfiguration<false>,
- Aws::Endpoint::BuiltInParameters,
- Aws::Endpoint::ClientContextParameters>;
- char CharToDec(const char c)
- {
- if(c >= '0' && c <= '9')
- return c - '0';
- if(c >= 'A' && c <= 'F')
- return c - 'A' + 10;
- if(c >= 'a' && c <= 'f')
- return c - 'a' + 10;
- return 0;
- }
- Aws::String PercentDecode(Aws::String inputString)
- {
- if (inputString.find_first_of("%") == Aws::String::npos)
- {
- return inputString;
- }
- Aws::String result;
- result.reserve(inputString.size());
- bool percentFound = false;
- char firstOctet = 0;
- char secondOctet = 0;
- for(size_t i = 0; i < inputString.size(); ++i)
- {
- const char currentChar = inputString[i];
- if ('%' == currentChar)
- {
- if (percentFound)
- {
- // not percent-encoded string
- result += currentChar;
- }
- percentFound = true;
- continue;
- }
- if (percentFound)
- {
- if ((currentChar >= '0' && currentChar <= '9') ||
- (currentChar >= 'A' && currentChar <= 'F') ||
- (currentChar >= 'a' && currentChar <= 'f'))
- {
- if(!firstOctet)
- {
- firstOctet = currentChar;
- continue;
- }
- if(!secondOctet)
- {
- secondOctet = currentChar;
- char encodedChar = CharToDec(firstOctet) * 16 + CharToDec(secondOctet);
- result += encodedChar;
- percentFound = false;
- firstOctet = 0;
- secondOctet = 0;
- continue;
- }
- } else {
- // Non-percent encoded sequence
- result += '%';
- if(!firstOctet)
- result += firstOctet;
- result += currentChar;
- percentFound = false;
- firstOctet = 0;
- secondOctet = 0;
- continue;
- }
- }
- if ('+' == currentChar)
- {
- result += ' ';
- continue;
- }
- result += currentChar;
- }
- return result;
- }
- AWS_CORE_API ResolveEndpointOutcome
- ResolveEndpointDefaultImpl(const Aws::Crt::Endpoints::RuleEngine& ruleEngine,
- const EndpointParameters& builtInParameters,
- const EndpointParameters& clientContextParameters,
- const EndpointParameters& endpointParameters)
- {
- if(!ruleEngine) {
- AWS_LOGSTREAM_FATAL(DEFAULT_ENDPOINT_PROVIDER_TAG, "Invalid CRT Rule Engine state");
- return ResolveEndpointOutcome(
- Aws::Client::AWSError<Aws::Client::CoreErrors>(
- Aws::Client::CoreErrors::INTERNAL_FAILURE,
- "",
- "CRT Endpoint rule engine is not initialized",
- false/*retryable*/));
- }
- Aws::Crt::Endpoints::RequestContext crtRequestCtx;
- const Aws::Vector<std::reference_wrapper<const EndpointParameters>> allParameters
- = {std::cref(builtInParameters), std::cref(clientContextParameters), std::cref(endpointParameters)};
- for (const auto& parameterClass : allParameters)
- {
- for(const auto& parameter : parameterClass.get())
- {
- if(EndpointParameter::ParameterType::BOOLEAN == parameter.GetStoredType())
- {
- AWS_LOGSTREAM_TRACE(DEFAULT_ENDPOINT_PROVIDER_TAG, "Endpoint bool eval parameter: " << parameter.GetName() << " = " << parameter.GetBoolValueNoCheck());
- crtRequestCtx.AddBoolean(Aws::Crt::ByteCursorFromCString(parameter.GetName().c_str()), parameter.GetBoolValueNoCheck());
- }
- else if(EndpointParameter::ParameterType::STRING == parameter.GetStoredType())
- {
- AWS_LOGSTREAM_TRACE(DEFAULT_ENDPOINT_PROVIDER_TAG, "Endpoint str eval parameter: " << parameter.GetName() << " = " << parameter.GetStrValueNoCheck());
- crtRequestCtx.AddString(Aws::Crt::ByteCursorFromCString(parameter.GetName().c_str()), Aws::Crt::ByteCursorFromCString(parameter.GetStrValueNoCheck().c_str()));
- }
- else
- {
- return ResolveEndpointOutcome(
- Aws::Client::AWSError<Aws::Client::CoreErrors>(
- Aws::Client::CoreErrors::INVALID_QUERY_PARAMETER,
- "",
- "Invalid endpoint parameter type for parameter " + parameter.GetName(),
- false/*retryable*/));
- }
- }
- }
- auto resolved = ruleEngine.Resolve(crtRequestCtx);
- if(resolved.has_value())
- {
- if(resolved->IsError())
- {
- auto crtError = resolved->GetError();
- Aws::String sdkCrtError = crtError ? Aws::String(crtError->begin(), crtError->end()) :
- "CRT Rule engine resolution resulted in an unknown error";
- return ResolveEndpointOutcome(
- Aws::Client::AWSError<Aws::Client::CoreErrors>(
- Aws::Client::CoreErrors::INVALID_PARAMETER_COMBINATION,
- "",
- sdkCrtError,
- false/*retryable*/));
- }
- else if(resolved->IsEndpoint() && resolved->GetUrl())
- {
- Aws::Endpoint::AWSEndpoint endpoint;
- const auto crtUrl = resolved->GetUrl();
- Aws::String sdkCrtUrl = Aws::String(crtUrl->begin(), crtUrl->end());
- AWS_LOGSTREAM_DEBUG(DEFAULT_ENDPOINT_PROVIDER_TAG, "Endpoint rules engine evaluated the endpoint: " << sdkCrtUrl);
- endpoint.SetURL(PercentDecode(std::move(sdkCrtUrl)));
- // Transform attributes
- // Each attribute consist of properties, hence converting CRT properties to SDK attributes
- const auto crtProps = resolved->GetProperties();
- if (crtProps && crtProps->size() > 2) {
- Aws::String sdkCrtProps = crtProps ? Aws::String(crtProps->begin(), crtProps->end()) : "";
- AWS_LOGSTREAM_TRACE(DEFAULT_ENDPOINT_PROVIDER_TAG, "Endpoint rules evaluated props: " << sdkCrtProps);
- Internal::Endpoint::EndpointAttributes epAttributes = Internal::Endpoint::EndpointAttributes::BuildEndpointAttributesFromJson(
- sdkCrtProps);
- endpoint.SetAttributes(std::move(epAttributes));
- }
- // transform headers
- const auto crtHeaders = resolved->GetHeaders();
- if (crtHeaders)
- {
- Aws::UnorderedMap<Aws::String, Aws::String> sdkHeaders;
- for (const auto& header: *crtHeaders)
- {
- Aws::String key(header.first.begin(), header.first.end());
- Aws::String value;
- for (const auto& crtHeaderValue : header.second)
- {
- if(!value.empty()) {
- value.insert(value.end(), ';');
- }
- value.insert(value.end(), crtHeaderValue.begin(), crtHeaderValue.end());
- }
- sdkHeaders.emplace(std::move(key), std::move(value));
- }
- endpoint.SetHeaders(std::move(sdkHeaders));
- }
- return ResolveEndpointOutcome(std::move(endpoint));
- }
- else
- {
- return ResolveEndpointOutcome(
- Aws::Client::AWSError<Aws::Client::CoreErrors>(
- Aws::Client::CoreErrors::INVALID_QUERY_PARAMETER,
- "",
- "Invalid AWS CRT RuleEngine state",
- false/*retryable*/));
- }
- }
- auto errCode = Aws::Crt::LastError();
- AWS_LOGSTREAM_DEBUG(DEFAULT_ENDPOINT_PROVIDER_TAG, "ERROR: Rule engine has failed to evaluate the endpoint: " << errCode << " " << Aws::Crt::ErrorDebugString(errCode));
- return ResolveEndpointOutcome(
- Aws::Client::AWSError<Aws::Client::CoreErrors>(
- Aws::Client::CoreErrors::INVALID_QUERY_PARAMETER,
- "",
- "Failed to evaluate the endpoint: null output from AWS CRT RuleEngine",
- false/*retryable*/));
- }
- } // namespace Endpoint
- } // namespace Aws
|