S3 - Only add metadata once; use binary file content

This commit is contained in:
Bert Blommers 2020-07-12 18:29:10 +01:00
parent b33c5dff06
commit 8b63421321
3 changed files with 15 additions and 12 deletions

View File

@ -1081,7 +1081,7 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
return 403, {}, "" return 403, {}, ""
elif signed_url: elif signed_url:
# coming in from requests.get(s3.generate_presigned_url()) # coming in from requests.get(s3.generate_presigned_url())
if self._invalid_headers(request.url, dict(headers)): if self._invalid_headers(request.url, dict(request.headers)):
return 403, {}, S3_INVALID_PRESIGNED_PARAMETERS return 403, {}, S3_INVALID_PRESIGNED_PARAMETERS
if hasattr(request, "body"): if hasattr(request, "body"):

View File

@ -6,6 +6,7 @@ from boto.s3.key import Key
import re import re
import six import six
from six.moves.urllib.parse import urlparse, unquote, quote from six.moves.urllib.parse import urlparse, unquote, quote
from requests.structures import CaseInsensitiveDict
import sys import sys
@ -62,7 +63,7 @@ def parse_region_from_url(url):
def metadata_from_headers(headers): def metadata_from_headers(headers):
metadata = {} metadata = CaseInsensitiveDict()
meta_regex = re.compile(r"^x-amz-meta-([a-zA-Z0-9\-_]+)$", flags=re.IGNORECASE) meta_regex = re.compile(r"^x-amz-meta-([a-zA-Z0-9\-_]+)$", flags=re.IGNORECASE)
for header, value in headers.items(): for header, value in headers.items():
if isinstance(header, six.string_types): if isinstance(header, six.string_types):

View File

@ -4612,6 +4612,7 @@ def test_presigned_url_restrict_parameters():
def test_presigned_put_url_with_approved_headers(): def test_presigned_put_url_with_approved_headers():
bucket = str(uuid.uuid4()) bucket = str(uuid.uuid4())
key = "file.txt" key = "file.txt"
content = b"filecontent"
expected_contenttype = "app/sth" expected_contenttype = "app/sth"
conn = boto3.resource("s3", region_name="us-east-1") conn = boto3.resource("s3", region_name="us-east-1")
conn.create_bucket(Bucket=bucket) conn.create_bucket(Bucket=bucket)
@ -4624,26 +4625,26 @@ def test_presigned_put_url_with_approved_headers():
) )
# Verify S3 throws an error when the header is not provided # Verify S3 throws an error when the header is not provided
response = requests.put(url, data="filecontent") response = requests.put(url, data=content)
response.status_code.should.equal(403) response.status_code.should.equal(403)
response.content.should.contain("<Code>SignatureDoesNotMatch</Code>") str(response.content).should.contain("<Code>SignatureDoesNotMatch</Code>")
response.content.should.contain( str(response.content).should.contain(
"<Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>" "<Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>"
) )
# Verify S3 throws an error when the header has the wrong value # Verify S3 throws an error when the header has the wrong value
response = requests.put( response = requests.put(
url, data="filecontent", headers={"Content-Type": "application/unknown"} url, data=content, headers={"Content-Type": "application/unknown"}
) )
response.status_code.should.equal(403) response.status_code.should.equal(403)
response.content.should.contain("<Code>SignatureDoesNotMatch</Code>") str(response.content).should.contain("<Code>SignatureDoesNotMatch</Code>")
response.content.should.contain( str(response.content).should.contain(
"<Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>" "<Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>"
) )
# Verify S3 uploads correctly when providing the meta data # Verify S3 uploads correctly when providing the meta data
response = requests.put( response = requests.put(
url, data="filecontent", headers={"Content-Type": expected_contenttype} url, data=content, headers={"Content-Type": expected_contenttype}
) )
response.status_code.should.equal(200) response.status_code.should.equal(200)
@ -4651,7 +4652,7 @@ def test_presigned_put_url_with_approved_headers():
obj = s3.get_object(Bucket=bucket, Key=key) obj = s3.get_object(Bucket=bucket, Key=key)
obj["ContentType"].should.equal(expected_contenttype) obj["ContentType"].should.equal(expected_contenttype)
obj["ContentLength"].should.equal(11) obj["ContentLength"].should.equal(11)
obj["Body"].read().should.equal("filecontent") obj["Body"].read().should.equal(content)
obj["Metadata"].should.equal({}) obj["Metadata"].should.equal({})
s3.delete_object(Bucket=bucket, Key=key) s3.delete_object(Bucket=bucket, Key=key)
@ -4662,6 +4663,7 @@ def test_presigned_put_url_with_approved_headers():
def test_presigned_put_url_with_custom_headers(): def test_presigned_put_url_with_custom_headers():
bucket = str(uuid.uuid4()) bucket = str(uuid.uuid4())
key = "file.txt" key = "file.txt"
content = b"filecontent"
conn = boto3.resource("s3", region_name="us-east-1") conn = boto3.resource("s3", region_name="us-east-1")
conn.create_bucket(Bucket=bucket) conn.create_bucket(Bucket=bucket)
s3 = boto3.client("s3", region_name="us-east-1") s3 = boto3.client("s3", region_name="us-east-1")
@ -4673,13 +4675,13 @@ def test_presigned_put_url_with_custom_headers():
) )
# Verify S3 uploads correctly when providing the meta data # Verify S3 uploads correctly when providing the meta data
response = requests.put(url, data="filecontent") response = requests.put(url, data=content)
response.status_code.should.equal(200) response.status_code.should.equal(200)
# Assert the object exists # Assert the object exists
obj = s3.get_object(Bucket=bucket, Key=key) obj = s3.get_object(Bucket=bucket, Key=key)
obj["ContentLength"].should.equal(11) obj["ContentLength"].should.equal(11)
obj["Body"].read().should.equal("filecontent") obj["Body"].read().should.equal(content)
obj["Metadata"].should.equal({"venue": "123"}) obj["Metadata"].should.equal({"venue": "123"})
s3.delete_object(Bucket=bucket, Key=key) s3.delete_object(Bucket=bucket, Key=key)