Skip to content

S3Client::GeneratePresignedUrl return invalid url when key contains spaces #2396

@wcw84

Description

@wcw84

Describe the bug

S3Client::GeneratePresignedUrl return an invalid signed url when the key contains space, which should be url encoded to %20, but not %2520.
For example, I have an object with key "Anson Lo", the url signed should be:

https://my_bucket_url/Anson%20Lo?X-Amz-Algorithm=...

but currently, the GeneratePresignedUrl would return:

https://my_bucket_url/Anson%2520Lo?X-Amz-Algorithm=...
which will get 404 response from the server.

Expected Behavior

The signed url return by GeneratePresignedUrl should like:
https://transcoder-chuanwen.s3.ap-southeast-1.amazonaws.com/Anson%20Lo?X-Amz-Algorithm=...

Current Behavior

https://transcoder-chuanwen.s3.ap-southeast-1.amazonaws.com/Anson%2520Lo?X-Amz-Algorithm=...

Reproduction Steps

#include <aws/core/Aws.h>
#include <aws/core/utils/logging/LogLevel.h>
#include <aws/s3/S3Client.h>
#include <iostream>
#include <aws/core/http/HttpTypes.h>

using namespace Aws;
int main()
{
    SDKOptions options;
    options.loggingOptions.logLevel = Utils::Logging::LogLevel::Debug;
    
    InitAPI(options); 
    {
        auto bucket = "transcoder-chuanwen";
        String key = "Anson Lo";

        Aws::Client::ClientConfiguration clientConfig;
        clientConfig.region = "ap-southeast-1";
        S3::S3Client client(clientConfig);
        auto response = client.GeneratePresignedUrl(bucket, key, Aws::Http::HttpMethod::HTTP_GET, 3600);
        std::cout << "bucket: " << bucket << std::endl;
        std::cout << "key: " << key << std::endl;
        std::cout << "signed url: " << response << std::endl;
    }

    ShutdownAPI(options);
    return 0;
}

This code will print the signed url, like:

https://transcoder-chuanwen.s3.ap-southeast-1.amazonaws.com/Anson%2520Lo?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIA2VXHONZRP5AZQ25K%2F20230315%2Fap-southeast-1%2Fs3%2Faws4_request&X-Amz-Date=20230315T055245Z&X-Amz-Expires=3600&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEC4aDmFwLXNvdXRoZWFzdC0xIkcwRQIhANooLDoVtLF3ShaajKnnCez2ET4l9pqZue6E1sMxChMBAiAdiZU3Ge7PPZndUYwLW6O9rFQbV6viAztqSyjmX%2BBTAirUBQjn%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F8BEAAaDDczMzg1MTA1MzY2NiIMkttq97FT4LXcwYi5KqgF4NFHrPCen9movBxrS%2BHgl21Awtx0sBeD8hB9pKsi6t9YJ6mi1u%2BhO2NVt37%2BRMCqqnF7AlI%2Bk29VKYcUp9ZQZH7RSgzQ%2BTK5wngj6FRvo3GUjzp4urXlFoDBBtaR3onsefXjU8K9W%2B2VA%2FtQ2jXVAloMd77cF4gOPwQWlMuyE7eVekvM9%2BzXGySbj88L1gxOb8LA3PsPgXDEcYjAeFzeeUHJArEmHJGui5%2FoLdOyBl0XtAiq3I1rVOHC8T50dZ6A%2F%2FK62TO9rgO0uwYUN0J3Qv3aHXZfAgt4ylbruAmrphxsDFqFK9jbNvdcKr70nCfYGbjAl3TwiVBjMY%2BGsiepktxtB7aSYm8asFPohhpWg0BSWQNg1vXeyL8e2C%2B5QLLs8i9S5shqlgDuYjqU1K71RUbbIJI4yYgczxUe4qMqjPtWoLGqWZlpVKLAu3ALNhRXPC7cZImaitdYMmGagKvz9dDnCVV5IzaSXXaBxyzmzNWU5er4jprgyULbUOFyCbsEdXjIhjHv88ptnCb76YxQmofamldooMVGNsMZkrutG3UgHtUzYyc0a7oFlUUVtyWayCOQoXwXsUVW5yjrldC8%2Fehij53VbUjPCYV3eOr0OXQs518kSXveIeqfTu3TY%2BwV0aAPZeKocDfRfGTTrRcWV23hsFps0fsBbilZz6Qz8r0sCajJWmw89yYkF%2FeF%2Bsj5gx07QizOagbBfuLDRchPRcS1hYZDKT7IHfMyG0UUAqP%2F%2FZD6v%2B1Dr6vXfYOSmaFhM8gTXB9cfSg32bFMos1niuQu9EoY1krBwljOMi9s1Ry%2FJWLipNJBsN7UHU9NXIpiCCN3hLAoXdF6jJumVn46Kh0N0vRh5Np8ia8AyMcuqQOb1kxsEXnCa8rSNAm%2BGZXm8dvtDnCCEA8wlrHFoAY6sQFNl5xYLpWvR3lIaNFb6Bvx86xxrk0KJxRnXTDsOG%2FWvQAvwZUG56vswpiEXU1%2BjTiZnbMDTH8nyv3l77DrXUKdL0zOndtUii50JNaQWslIFlL4J%2BPKo0bFBcU9jCUxHxAmYPtb7bTsWgKCtoS5ROddmjsiEINv9N2diLoTiDW75FPnmpleBt37CB0l1%2FmMG4u%2FLC%2BRuViuBZks3zwCQbjFBagRZ%2B2tfAG%2BKbZTk9ueSFc%3D&X-Amz-SignedHeaders=host&X-Amz-Signature=f7a3cb9629e1ef1d2accc7eb02d63319df7b6d050eb260c233159b0a620304bc

And Then curl it:

# curl -i 'https://transcoder-chuanwen.s3.ap-southeast-1.amazonaws.com/Anson%2520Lo?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIA2VXHONZRP5AZQ25K%2F20230315%2Fap-southeast-1%2Fs3%2Faws4_request&X-Amz-Date=20230315T055245Z&X-Amz-Expires=3600&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEC4aDmFwLXNvdXRoZWFzdC0xIkcwRQIhANooLDoVtLF3ShaajKnnCez2ET4l9pqZue6E1sMxChMBAiAdiZU3Ge7PPZndUYwLW6O9rFQbV6viAztqSyjmX%2BBTAirUBQjn%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F8BEAAaDDczMzg1MTA1MzY2NiIMkttq97FT4LXcwYi5KqgF4NFHrPCen9movBxrS%2BHgl21Awtx0sBeD8hB9pKsi6t9YJ6mi1u%2BhO2NVt37%2BRMCqqnF7AlI%2Bk29VKYcUp9ZQZH7RSgzQ%2BTK5wngj6FRvo3GUjzp4urXlFoDBBtaR3onsefXjU8K9W%2B2VA%2FtQ2jXVAloMd77cF4gOPwQWlMuyE7eVekvM9%2BzXGySbj88L1gxOb8LA3PsPgXDEcYjAeFzeeUHJArEmHJGui5%2FoLdOyBl0XtAiq3I1rVOHC8T50dZ6A%2F%2FK62TO9rgO0uwYUN0J3Qv3aHXZfAgt4ylbruAmrphxsDFqFK9jbNvdcKr70nCfYGbjAl3TwiVBjMY%2BGsiepktxtB7aSYm8asFPohhpWg0BSWQNg1vXeyL8e2C%2B5QLLs8i9S5shqlgDuYjqU1K71RUbbIJI4yYgczxUe4qMqjPtWoLGqWZlpVKLAu3ALNhRXPC7cZImaitdYMmGagKvz9dDnCVV5IzaSXXaBxyzmzNWU5er4jprgyULbUOFyCbsEdXjIhjHv88ptnCb76YxQmofamldooMVGNsMZkrutG3UgHtUzYyc0a7oFlUUVtyWayCOQoXwXsUVW5yjrldC8%2Fehij53VbUjPCYV3eOr0OXQs518kSXveIeqfTu3TY%2BwV0aAPZeKocDfRfGTTrRcWV23hsFps0fsBbilZz6Qz8r0sCajJWmw89yYkF%2FeF%2Bsj5gx07QizOagbBfuLDRchPRcS1hYZDKT7IHfMyG0UUAqP%2F%2FZD6v%2B1Dr6vXfYOSmaFhM8gTXB9cfSg32bFMos1niuQu9EoY1krBwljOMi9s1Ry%2FJWLipNJBsN7UHU9NXIpiCCN3hLAoXdF6jJumVn46Kh0N0vRh5Np8ia8AyMcuqQOb1kxsEXnCa8rSNAm%2BGZXm8dvtDnCCEA8wlrHFoAY6sQFNl5xYLpWvR3lIaNFb6Bvx86xxrk0KJxRnXTDsOG%2FWvQAvwZUG56vswpiEXU1%2BjTiZnbMDTH8nyv3l77DrXUKdL0zOndtUii50JNaQWslIFlL4J%2BPKo0bFBcU9jCUxHxAmYPtb7bTsWgKCtoS5ROddmjsiEINv9N2diLoTiDW75FPnmpleBt37CB0l1%2FmMG4u%2FLC%2BRuViuBZks3zwCQbjFBagRZ%2B2tfAG%2BKbZTk9ueSFc%3D&X-Amz-SignedHeaders=host&X-Amz-Signature=f7a3cb9629e1ef1d2accc7eb02d63319df7b6d050eb260c233159b0a620304bc'
HTTP/1.1 404 Not Found
x-amz-request-id: EHETX5JZGYHFDZ76
x-amz-id-2: y+zQNERxLty/itTfxOi8toiCJ2HYofKWFBSAsCWjhtPLVQpbJ9SWIH0vZOBOcvRqfenMGDVhPbo=
Content-Type: application/xml
Transfer-Encoding: chunked
Date: Wed, 15 Mar 2023 05:57:37 GMT
Server: AmazonS3

<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>NoSuchKey</Code><Message>The specified key does not exist.</Message><Key>Anson%20Lo</Key><RequestId>EHETX5JZGYHFDZ76</RequestId><HostId>y+zQNERxLty/itTfxOi8toiCJ2HYofKWFBSAsCWjhtPLVQpbJ9SWIH0vZOBOcvRqfenMGDVhPbo=</HostId></Error>

Possible Solution

I find a way to work around via changing the sdk source:

diff --git a/generated/src/aws-cpp-sdk-s3/source/S3Client.cpp b/generated/src/aws-cpp-sdk-s3/source/S3Client.cpp
index 270b368b6c..5356ef2c5e 100644
--- a/generated/src/aws-cpp-sdk-s3/source/S3Client.cpp
+++ b/generated/src/aws-cpp-sdk-s3/source/S3Client.cpp
@@ -2027,9 +2027,7 @@ Aws::String S3Client::GeneratePresignedUrl(const Aws::String& bucket,
         return {};
     }
     Aws::Endpoint::AWSEndpoint& endpoint = computeEndpointOutcome.GetResult();
-    URI uri(endpoint.GetURL());
-    uri.SetPath(uri.GetPath() + "/" + key);
-    endpoint.SetURL(uri.GetURIString());
+    endpoint.SetURL(endpoint.GetURL() + "/" + key);  // fixed
     return AWSClient::GeneratePresignedUrl(endpoint, method, customizedHeaders, expirationInSeconds);
 }

Additional Information/Context

No response

AWS CPP SDK version used

commit 0be2ba4 tag: 1.11.36

Compiler and Version used

clang version 11.1.0 (Amazon Linux 2 11.1.0-1.amzn2.0.2)

Operating System and version

Amazon Linux 2 11.1.0-1.amzn2.0.2

Metadata

Metadata

Assignees

Labels

bugThis issue is a bug.needs-reproductionThis issue needs reproduction.p2This is a standard priority issue

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions