Skip to content

Commit

Permalink
Use regular URI Query Path encoding according to RFC 3986 by default
Browse files Browse the repository at this point in the history
  • Loading branch information
SergeyRyabinin committed Oct 10, 2023
1 parent 88cfe94 commit aa88365
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 51 deletions.
5 changes: 5 additions & 0 deletions src/aws-cpp-sdk-core/include/aws/core/endpoint/AWSEndpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ namespace Aws
m_uri.AddPathSegments(std::forward<T>(pathSegments));
}

inline void SetLegacyEncoded(bool legacyEncoding)
{
m_uri.SetLegacyEncoded(legacyEncoding);
}

using OptionalError = Crt::Optional<Aws::Client::AWSError<Aws::Client::CoreErrors>>;
OptionalError AddPrefixIfMissing(const Aws::String& prefix);

Expand Down
13 changes: 12 additions & 1 deletion src/aws-cpp-sdk-core/include/aws/core/http/URI.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ namespace Aws
Aws::String segments = ss.str();
for (const auto& segment : Aws::Utils::StringUtils::Split(segments, '/'))
{
m_pathSegments.push_back(segment);
m_pathSegments.push_back(segment.c_str());
}
m_pathHasTrailingSlash = (!segments.empty() && segments.back() == '/');
}
Expand Down Expand Up @@ -180,6 +180,16 @@ namespace Aws
*/
Aws::String GetURIString(bool includeQueryString = true) const;

/**
* Returns true if this URI is going to be encoded in legacy, non compliant to Rfc3986 mode
*/
inline bool IsLegacyEncoded() const { return m_useLegacyEncoding; }

/**
* Sets legacy encoding mode (Rfc3986 compliant). False (i.e. use Rfc3986) is the default.
*/
inline void SetLegacyEncoded(const bool value) { m_useLegacyEncoding = value; }

/**
* URLEncodes the path portions of path (doesn't encode the "/" portion)
* Keeps the first and the last "/".
Expand All @@ -205,6 +215,7 @@ namespace Aws
uint16_t m_port = HTTP_DEFAULT_PORT;
Aws::Vector<Aws::String> m_pathSegments;
bool m_pathHasTrailingSlash = false;
bool m_useLegacyEncoding = false;
Aws::String m_queryString;
};

Expand Down
5 changes: 5 additions & 0 deletions src/aws-cpp-sdk-core/include/aws/core/utils/StringUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ namespace Aws
*/
static Aws::String URLEncode(const char* unsafe);

static inline Aws::String URLEncode(const Aws::String& unsafe)
{
return URLEncode(unsafe.c_str());
}

/**
* Http Clients tend to escape some characters but not all. Escaping all of them causes problems, because the client
* will also try to escape them.
Expand Down
6 changes: 3 additions & 3 deletions src/aws-cpp-sdk-core/source/http/URI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ const char* SEPARATOR = "://";
bool s_compliantRfc3986Encoding = false;
void SetCompliantRfc3986Encoding(bool compliant) { s_compliantRfc3986Encoding = compliant; }

Aws::String urlEncodeSegment(const Aws::String& segment)
Aws::String urlEncodeSegment(const Aws::String& segment, bool legacyEncoding = false)
{
// consolidates legacy escaping logic into one local method
if (s_compliantRfc3986Encoding)
if (!legacyEncoding || s_compliantRfc3986Encoding)
{
return StringUtils::URLEncode(segment.c_str());
}
Expand Down Expand Up @@ -237,7 +237,7 @@ Aws::String URI::GetURLEncodedPathRFC3986() const
// (mostly; there is some non-standards legacy support that can be disabled)
for (const auto& segment : m_pathSegments)
{
ss << '/' << urlEncodeSegment(segment);
ss << '/' << urlEncodeSegment(segment, m_useLegacyEncoding);
}

if (m_pathSegments.empty() || m_pathHasTrailingSlash)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.amazonaws.util.awsclientgenerator.transform.CoreErrors;
import com.google.common.base.CaseFormat;
import com.google.common.collect.ImmutableSet;
import org.apache.commons.lang3.StringUtils;

import java.lang.RuntimeException;

Expand Down Expand Up @@ -481,4 +482,8 @@ public static String checkForCollision(
.map(__ -> prefix + cppType)
.orElse(functionName);
}

public static Boolean containsAnyLegacyAwsUriNonEncodedChar(String str) {
return StringUtils.containsAny(str, "$&,:=@");
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#if($serviceModel.endpointRules)
#if(($serviceNamespace == "S3Crt" && $operation.s3CrtEnabled) || $operation.getRequest().getShape().hasEventStreamMembers())
#set($meterNeeded = true)
#set($indent = "")
Expand Down Expand Up @@ -37,7 +36,6 @@ ${indent} CoreErrors::ENDPOINT_RESOLUTION_FAILURE, "ENDPOINT_RESOLUTION
${indent} return;
${indent} }
#end
#end
#if($operation.http.requestUri.contains("?"))
${indent} Aws::StringStream ss;
#end
Expand All @@ -54,19 +52,17 @@ ${indent} Aws::StringStream ss;
#set($queryStart = true)
#set($pathAndQuery = $operation.http.splitUriPartIntoPathAndQuery($uriPartString))
#if(!$pathAndQuery.get(0).isEmpty())
#if($serviceModel.endpointRules)
${indent} endpointResolutionOutcome.GetResult().AddPathSegments("${pathAndQuery.get(0)}");
#else
${indent} uri.AddPathSegments("${pathAndQuery.get(0)}");
#if($CppViewHelper.containsAnyLegacyAwsUriNonEncodedChar(${pathAndQuery.get(0)}))
${indent} endpointResolutionOutcome.GetResult().SetLegacyEncoded(true);
#end
${indent} endpointResolutionOutcome.GetResult().AddPathSegments("${pathAndQuery.get(0)}");
#end
${indent} ss.str("${pathAndQuery.get(1)}");
#elseif(!$uriPartString.equals("/"))
#if($serviceModel.endpointRules)
${indent} endpointResolutionOutcome.GetResult().AddPathSegments("$uriPartString");
#else
${indent} uri.AddPathSegments("$uriPartString");
#if($CppViewHelper.containsAnyLegacyAwsUriNonEncodedChar($uriPartString))
${indent} endpointResolutionOutcome.GetResult().SetLegacyEncoded(true);
#end
${indent} endpointResolutionOutcome.GetResult().AddPathSegments("$uriPartString");
#end## ---------------------------- if (request uri contains query) end ------
#foreach($var in $uriVars)## for (parameter in request uri parameters) -------
#set($varIndex = $partIndex - 1)
Expand All @@ -83,17 +79,12 @@ ${indent} uri.AddPathSegments("$uriPartString");
${indent} ss << $parameter;
#else
#if($greedySyntax)
#if($serviceModel.endpointRules)
${indent} endpointResolutionOutcome.GetResult().AddPathSegments($parameter);
#else
${indent} uri.AddPathSegments($parameter);
#if($CppViewHelper.containsAnyLegacyAwsUriNonEncodedChar($parameter))
${indent} endpointResolutionOutcome.GetResult().SetLegacyEncoded(true);
#end
${indent} endpointResolutionOutcome.GetResult().AddPathSegments($parameter);
#else
#if($serviceModel.endpointRules)
${indent} endpointResolutionOutcome.GetResult().AddPathSegment($parameter);
#else
${indent} uri.AddPathSegment($parameter);
#end
#end
#end
#if($uriParts.size() > $partIndex)
Expand All @@ -102,19 +93,17 @@ ${indent} uri.AddPathSegment($parameter);
#set($queryStart = true)
#set($pathAndQuery = $operation.http.splitUriPartIntoPathAndQuery($uriPartString))
#if(!$pathAndQuery.get(0).isEmpty())
#if($serviceModel.endpointRules)
${indent} endpointResolutionOutcome.GetResult().AddPathSegments("${pathAndQuery.get(0)}");
#else
${indent} uri.AddPathSegments("${pathAndQuery.get(0)}");
#if($CppViewHelper.containsAnyLegacyAwsUriNonEncodedChar(${pathAndQuery.get(0)}))
${indent} endpointResolutionOutcome.GetResult().SetLegacyEncoded(true);
#end
${indent} endpointResolutionOutcome.GetResult().AddPathSegments("${pathAndQuery.get(0)}");
#end
${indent} ss.str("${pathAndQuery.get(1)}");
#elseif(!$uriPartString.equals("/"))
#if($serviceModel.endpointRules)
${indent} endpointResolutionOutcome.GetResult().AddPathSegments("$uriPartString");
#else
${indent} uri.AddPathSegments("$uriPartString");
#if($CppViewHelper.containsAnyLegacyAwsUriNonEncodedChar($uriPartString))
${indent} endpointResolutionOutcome.GetResult().SetLegacyEncoded(true);
#end
${indent} endpointResolutionOutcome.GetResult().AddPathSegments("$uriPartString");
#end
#end
#end## --------------------- if !skipFirst end ---
Expand All @@ -123,9 +112,5 @@ ${indent} uri.AddPathSegments("$uriPartString");
#end## --------------------- if uriParts.size() > startIndex end ---
#end## --------------------- for (parameter in request uri parameters) end ---
#if($queryStart)
#if($serviceModel.endpointRules)
${indent} endpointResolutionOutcome.GetResult().SetQueryString(ss.str());
#else
${indent} uri.SetQueryString(ss.str());
#end
#end
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
${operation.name}Outcome ${className}::${operation.name}() const
{
AWS_OPERATION_GUARD(${operation.name});
#if(!$serviceModel.endpointRules)
Aws::StringStream ss;
#if($metadata.hasEndpointTrait)
ss << m_baseUri << "${operation.http.requestUri}";
#else
ss << m_uri << "${operation.http.requestUri}";
#end
#end
AWS_OPERATION_CHECK_PTR(m_telemetryProvider, ${operation.name}, CoreErrors, CoreErrors::NOT_INITIALIZED);
auto tracer = m_telemetryProvider->getTracer(this->GetServiceClientName(), {});
auto meter = m_telemetryProvider->getMeter(this->GetServiceClientName(), {});
Expand All @@ -19,22 +11,17 @@ AWS_OPERATION_GUARD(${operation.name});
return TracingUtils::MakeCallWithTiming<${operation.name}Outcome>(
[&]()-> ${operation.name}Outcome {
#parse("com/amazonaws/util/awsclientgenerator/velocity/cpp/common/EndpointRulesNoRequestUriComputation.vm")
#if($serviceModel.endpointRules && $operation.http.requestUri && $operation.http.requestUri != "/")
#if($operation.http.requestUri && $operation.http.requestUri != "/")
#if($CppViewHelper.containsAnyLegacyAwsUriNonEncodedChar(${operation.http.requestUri}))
endpointResolutionOutcome.GetResult().SetLegacyEncoded(true);
#end
endpointResolutionOutcome.GetResult().AddPathSegments("${operation.http.requestUri}");
#end
#if($serviceModel.endpointRules)
#if($operation.result && $operation.result.shape.hasStreamMembers())
return ${operation.name}Outcome(MakeRequestWithUnparsedResponse(endpointResolutionOutcome.GetResult(), Aws::Http::HttpMethod::HTTP_${operation.http.method}, ${operation.signerName}, "${operation.name}"));
#else
return ${operation.name}Outcome(MakeRequest(endpointResolutionOutcome.GetResult(), Aws::Http::HttpMethod::HTTP_${operation.http.method}, ${operation.signerName}, "${operation.name}"));
#end
#else##-#if($serviceModel.endpointRules)
#if($operation.result && $operation.result.shape.hasStreamMembers())
return ${operation.name}Outcome(MakeRequestWithUnparsedResponse(ss.str(), Aws::Http::HttpMethod::HTTP_${operation.http.method}, ${operation.signerName}, "${operation.name}"));
#else
return ${operation.name}Outcome(MakeRequest(ss.str(), Aws::Http::HttpMethod::HTTP_${operation.http.method}, ${operation.signerName}, "${operation.name}"));
#end
#end##-#if($serviceModel.endpointRules)
},
TracingUtils::SMITHY_CLIENT_DURATION_METRIC,
*meter,
Expand Down

0 comments on commit aa88365

Please sign in to comment.