Describe the bug
When generating presigned URLs for CloudFront distributions, query parameters are not being transformed from their API parameter format (ResponseContentDisposition) to HTTP query string format (response-content-disposition).
Regression Issue
Expected Behavior
When calling generate_presigned_url() (from CloudFrontSigner) method with a URL containing query parameters like ResponseContentDisposition, the parameter should be transformed to its HTTP query string format (response-content-disposition) to match the S3 API specification defined in the service model at botocore/data/s3/2006-03-01/service-2.json:
"ResponseContentDisposition":{
"shape":"ResponseContentDisposition",
"documentation":"<p>Sets the <code>Content-Disposition</code> header of the response.</p>",
"location":"querystring",
"locationName":"response-content-disposition"
}
Current Behavior
The generate_presigned_url() method does not perform any query parameter transformation, resulting in URLs with incorrectly formatted query parameters and not returning a response with the response-content-disposition header.
Reproduction Steps
import os
import boto3
from botocore.signers import CloudFrontSigner
from datetime import datetime, timedelta
# Using CloudFront Signer
key_id="1234567"
rsa_signer = lambda message: b'signed'
cloudfront_signer = CloudFrontSigner(key_id, rsa_signer)
url_with_params = "https://test.cloudfront.net/myfile.pdf?ResponseContentDisposition=attachment%3Bfilename%3D%22download.pdf%22"
url = cloudfront_signer.generate_presigned_url(
url_with_params,
date_less_than=datetime.now() + timedelta(hours=1)
)
print(f"CLOUDFRONT: {url}")
# Using S3 Client (for comparison)
os.environ['AWS_ACCESS_KEY_ID'] = 'testing'
os.environ['AWS_SECRET_ACCESS_KEY'] = 'testing'
s3_client = boto3.client('s3')
url = s3_client.generate_presigned_url(
'get_object',
Params={
'Bucket': 'mybucket',
'Key': 'myfile.pdf',
'ResponseContentDisposition': 'attachment; filename="download.pdf"'
},
ExpiresIn=3600
)
print(f"S3: {url}")
output:
CLOUDFRONT: https://test.cloudfront.net/myfile.pdf?ResponseContentDisposition=attachment%3Bfilename%3D%22download.pdf%22&Expires=1764865633&Signature=c2lnbmVk&Key-Pair-Id=1234567
S3: https://mybucket.s3.amazonaws.com/myfile.pdf?response-content-disposition=attachment%3B%20filename%3D%22download.pdf%22&AWSAccessKeyId=testing&Signature=YCR4VzzJ2QzItrKyL4Q6%2F89nxuw%3D&Expires=1764876433
Possible Solution
No response
Additional Information/Context
Our project uses django-storages and for requests with s3, the response-content-disposition header is returning as expected in:
https://github.com/jschneier/django-storages/blob/ca89a94a7462a2423df460e7bfd5f847457042ca/storages/backends/s3.py#L697-L699
but with CloudFront, this part https://github.com/jschneier/django-storages/blob/ca89a94a7462a2423df460e7bfd5f847457042ca/storages/backends/s3.py#L685-L687 is not returning the header and the query parameter is also not updated.
We believe this is an issue in botocore because in s3
|
def generate_presigned_url( |
returns the query parameter with the expected format, while with cloudfront
|
def generate_presigned_url(self, url, date_less_than=None, policy=None): |
the query parameter is not modified .
SDK version used
1.42.2
Environment details (OS name and version, etc.)
Red Hat Enterprise Linux release 9.7
Describe the bug
When generating presigned URLs for CloudFront distributions, query parameters are not being transformed from their API parameter format (
ResponseContentDisposition) to HTTP query string format (response-content-disposition).Regression Issue
Expected Behavior
When calling
generate_presigned_url()(fromCloudFrontSigner) method with a URL containing query parameters likeResponseContentDisposition, the parameter should be transformed to its HTTP query string format (response-content-disposition) to match the S3 API specification defined in the service model atbotocore/data/s3/2006-03-01/service-2.json:Current Behavior
The
generate_presigned_url()method does not perform any query parameter transformation, resulting in URLs with incorrectly formatted query parameters and not returning a response with theresponse-content-dispositionheader.Reproduction Steps
output:
Possible Solution
No response
Additional Information/Context
Our project uses
django-storagesand for requests with s3, theresponse-content-dispositionheader is returning as expected in:https://github.com/jschneier/django-storages/blob/ca89a94a7462a2423df460e7bfd5f847457042ca/storages/backends/s3.py#L697-L699
but with CloudFront, this part https://github.com/jschneier/django-storages/blob/ca89a94a7462a2423df460e7bfd5f847457042ca/storages/backends/s3.py#L685-L687 is not returning the header and the query parameter is also not updated.
We believe this is an issue in
botocorebecause in s3botocore/botocore/signers.py
Line 756 in 4e6ef43
botocore/botocore/signers.py
Line 407 in 4e6ef43
SDK version used
1.42.2
Environment details (OS name and version, etc.)
Red Hat Enterprise Linux release 9.7