Merge pull request #2155 from gtmanfred/master

set default status for s3 posts and add success_action_redirect support
This commit is contained in:
Bert Blommers 2020-04-22 07:25:15 +01:00 committed by GitHub
commit 4575f359c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 62 additions and 7 deletions

View File

@ -5,9 +5,10 @@ import sys
import six
from botocore.awsrequest import AWSPreparedRequest
from werkzeug.wrappers import Request
from moto.core.utils import str_to_rfc_1123_datetime, py2_strip_unicode_keys
from six.moves.urllib.parse import parse_qs, urlparse, unquote
from six.moves.urllib.parse import parse_qs, urlparse, unquote, parse_qsl
import xmltodict
@ -777,6 +778,7 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
return 409, {}, template.render(bucket=removed_bucket)
def _bucket_response_post(self, request, body, bucket_name):
response_headers = {}
if not request.headers.get("Content-Length"):
return 411, {}, "Content-Length required"
@ -795,14 +797,18 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
if hasattr(request, "form"):
# Not HTTPretty
form = request.form
elif request.headers.get("Content-Type").startswith("multipart/form-data"):
request = Request.from_values(
input_stream=six.BytesIO(request.body),
content_length=request.headers["Content-Length"],
content_type=request.headers["Content-Type"],
method="POST",
)
form = request.form
else:
# HTTPretty, build new form object
body = body.decode()
form = {}
for kv in body.split("&"):
k, v = kv.split("=")
form[k] = v
form = dict(parse_qsl(body))
key = form["key"]
if "file" in form:
@ -810,13 +816,23 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
else:
f = request.files["file"].stream.read()
if "success_action_redirect" in form:
response_headers["Location"] = form["success_action_redirect"]
if "success_action_status" in form:
status_code = form["success_action_status"]
elif "success_action_redirect" in form:
status_code = 303
else:
status_code = 204
new_key = self.backend.set_key(bucket_name, key, f)
# Metadata
metadata = metadata_from_headers(form)
new_key.set_metadata(metadata)
return 200, {}, ""
return status_code, response_headers, ""
@staticmethod
def _get_path(request):

View File

@ -14,6 +14,7 @@ from io import BytesIO
import mimetypes
import zlib
import pickle
import uuid
import json
import boto
@ -4428,3 +4429,41 @@ def test_s3_config_dict():
assert not logging_bucket["supplementaryConfiguration"].get(
"BucketTaggingConfiguration"
)
@mock_s3
def test_creating_presigned_post():
bucket = "presigned-test"
s3 = boto3.client("s3", region_name="us-east-1")
s3.create_bucket(Bucket=bucket)
success_url = "http://localhost/completed"
fdata = b"test data\n"
file_uid = uuid.uuid4()
conditions = [
{"Content-Type": "text/plain"},
{"x-amz-server-side-encryption": "AES256"},
{"success_action_redirect": success_url},
]
conditions.append(["content-length-range", 1, 30])
data = s3.generate_presigned_post(
Bucket=bucket,
Key="{file_uid}.txt".format(file_uid=file_uid),
Fields={
"content-type": "text/plain",
"success_action_redirect": success_url,
"x-amz-server-side-encryption": "AES256",
},
Conditions=conditions,
ExpiresIn=1000,
)
resp = requests.post(
data["url"], data=data["fields"], files={"file": fdata}, allow_redirects=False
)
assert resp.headers["Location"] == success_url
assert resp.status_code == 303
assert (
s3.get_object(Bucket=bucket, Key="{file_uid}.txt".format(file_uid=file_uid))[
"Body"
].read()
== fdata
)