Brosef
Brosef

Reputation: 3095

what is the required order for S3 element values when making a Post request?

I'm trying to upload a file to S3 by doing :

r_response = requests.post(presigned_post["url"], json=presigned_post["fields"], files=files)

but I'm getting the following error:

Bucket POST must contain a field named 'key'. If it is specified, please check the order of the fields.

But I'm definitely including a key value. One other answer I saw recommended using a OrderedDict which I'm trying to do, but looking through the S3 documentation below, I don't see where it specifies a required order for they key,value data when making the request.

http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-HTTPPOSTForms.html http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-authentication-HTTPPOST.html

Anyone have any advice?

Boto3 returns a dictionary with the element values in the following order: x-amz-signature, x-amz-algorithm, key, x-amz-credential, policy, and x-amz-date and I'm just using the same dictionary.

def get_signed_request(title, type, track_id, file):
    S3_BUCKET = os.environ.get('S3_BUCKET')
    file_name = title
    file_type = type
    region = 'us-east-1'
    s3 = boto3.client('s3', region_name=region, config=Config(signature_version='s3v4'))

    presigned_post = s3.generate_presigned_post(
        Bucket = S3_BUCKET,
        Key = file_name
    )

    files = {'file': file}

    r_response = requests.post(presigned_post["url"], json=presigned_post["fields"], files=files)

Printing the contents of presigned_post shows the key:

 {'fields': {'x-amz-signature': '26eff5417d0d11a25dd294b059a088e2be37a97f14713962f4240c9f4e33febb', 'x-amz-algorithm': 'AWS4-HMAC-SHA256', 'key': u'sound.m4a', 'x-amz-credential': u'<AWSAccessID>/20161011/us-east-1/s3/aws4_request', 'policy': u'eyJjb25kaXRpb25zIjogW3siYnVja2V0IjogImZ1dHVyZWZpbGVzIn0sIHsia2V5IjogInNvdW5kLm00YSJ9LCB7IngtYW16LWFsZ29yaXRobSI6ICJBV1M0LUhNQUMtU0hBMjU2In0sIHsieC1hbXotY3JlZGVudGlhbCI6ICJBS0lBSTdLRktCTkJTNEM0VktKQS8yMDE2MTAxMS91cy1lYXN0LTEvczMvYXdzNF9yZXF1ZXN0In0sIHsieC1hbXotZGF0ZSI6ICIyMDE2MTAxMVQyMDM4NDlaIn1dLCAiZXhwaXJhdGlvbiI6ICIyMDE2LTEwLTExVDIxOjM4OjQ5WiJ9', 'x-amz-date': '20161011T203849Z'}, 'url': u'https://s3.amazonaws.com/bucketname'}

Upvotes: 1

Views: 1010

Answers (1)

Brosef
Brosef

Reputation: 3095

I was originally doing:

r_response = requests.post(presigned_post["url"], json=presigned_post["fields"], files=files)

I changed the json to data and it worked:

r_response = requests.post(presigned_post["url"], data=presigned_post["fields"], files=files)

Unfortunately, I was dealt another error:

<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>

Upvotes: 1

Related Questions