Skip to content

Commit

Permalink
Encode ARNs in RFC compliant mode
Browse files Browse the repository at this point in the history
  • Loading branch information
SergeyRyabinin committed Oct 17, 2023
1 parent 06c16a2 commit 0545f80
Show file tree
Hide file tree
Showing 9 changed files with 802 additions and 137 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 SetRfc3986Encoded(bool rfcEncoded)
{
m_uri.SetRfc3986Encoded(rfcEncoded);
}

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 @@ -180,6 +180,16 @@ namespace Aws
*/
Aws::String GetURIString(bool includeQueryString = true) const;

/**
* Returns true if this URI is going to be encoded in Rfc3986 compliant mode
*/
inline bool IsRfc3986Encoded() const { return m_useRfcEncoding; }

/**
* Sets Rfc3986 compliant encoding mode. False (i.e. use legacy encoding with some chars unescaped) is the default.
*/
inline void SetRfc3986Encoded(const bool value) { m_useRfcEncoding = value; }

/**
* URLEncodes the path portions of path (doesn't encode the "/" portion)
* Keeps the first and the last "/".
Expand All @@ -189,7 +199,7 @@ namespace Aws
/**
* URLEncodes the path portion of the URI according to RFC3986
*/
static Aws::String URLEncodePathRFC3986(const Aws::String& path);
static Aws::String URLEncodePathRFC3986(const Aws::String& path, bool = false);

private:
void ParseURIParts(const Aws::String& uri);
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_useRfcEncoding = 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
10 changes: 5 additions & 5 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 rfcEncoded = false)
{
// consolidates legacy escaping logic into one local method
if (s_compliantRfc3986Encoding)
if (rfcEncoded || s_compliantRfc3986Encoding)
{
return StringUtils::URLEncode(segment.c_str());
}
Expand Down Expand Up @@ -141,7 +141,7 @@ void URI::SetScheme(Scheme value)
}
}

Aws::String URI::URLEncodePathRFC3986(const Aws::String& path)
Aws::String URI::URLEncodePathRFC3986(const Aws::String& path, bool rfcEncoded)
{
if (path.empty())
{
Expand All @@ -155,7 +155,7 @@ Aws::String URI::URLEncodePathRFC3986(const Aws::String& path)
// escape characters appearing in a URL path according to RFC 3986
for (const auto& segment : pathParts)
{
ss << '/' << urlEncodeSegment(segment);
ss << '/' << urlEncodeSegment(segment, rfcEncoded);
}

// if the last character was also a slash, then add that back here.
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_useRfcEncoding);
}

if (m_pathSegments.empty() || m_pathHasTrailingSlash)
Expand Down
9 changes: 9 additions & 0 deletions tests/aws-cpp-sdk-core-tests/http/URITest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,15 @@ TEST_F(URITest, TestParseWithColon)
EXPECT_EQ(80, complexUri.GetPort());
EXPECT_STREQ("/awsnativesdkputobjectstestbucket20150702T200059Z/TestObject:1234/awsnativesdkputobjectstestbucket20150702T200059Z/TestObject:Key", complexUri.GetPath().c_str());
EXPECT_STREQ(strComplexUri, complexUri.GetURIString().c_str());

URI complexUriCompliant(strComplexUri);
complexUriCompliant.SetRfc3986Encoded(true);
EXPECT_STREQ("s3.us-east-1.amazonaws.com", complexUriCompliant.GetAuthority().c_str());
EXPECT_EQ(80, complexUriCompliant.GetPort());
EXPECT_STREQ("/awsnativesdkputobjectstestbucket20150702T200059Z/TestObject:1234/awsnativesdkputobjectstestbucket20150702T200059Z/TestObject:Key",
complexUri.GetPath().c_str());
EXPECT_STREQ("http://s3.us-east-1.amazonaws.com/awsnativesdkputobjectstestbucket20150702T200059Z/TestObject%3A1234/awsnativesdkputobjectstestbucket20150702T200059Z/TestObject%3AKey",
complexUriCompliant.GetURIString().c_str());
}

TEST_F(URITest, TestParseWithColonCompliant)
Expand Down
Loading

0 comments on commit 0545f80

Please sign in to comment.