3
votes

I am using the aws-sdk to get a pre-signed url for S3. I have the function wrapped in a lambda.

const aws = require('aws-sdk');

module.exports = CreateRecord => {
  CreateRecord.controllers.createSignature = (event, context, callback) => {
    const s3 = new aws.S3({
      signatureVersion: 'v4',
    });

    const params = {
      Bucket: 'random-test-bucket002',
      Key: 'test-key',
      Expires: 100
    };

    s3.getSignedUrl('putObject', params, function(err, signedUrl) {
      let response;
      if (err) {
        response = {
          statusCode: 500,
          headers: {
            'Access-Control-Allow-Origin': '*',
          },
          body: JSON.stringify({
            error: 'Did not receive signed url'
          }),
        };
      } else {
        response = {
          statusCode: 200,
          headers: {
            'Access-Control-Allow-Origin': '*', // Required for CORS support to work
          },
          body: JSON.stringify({
            message: `Url successfully created`,
            signedUrl,
          })
        };
      }
      callback(null, response);
    });
  };
};

This code works perfectly fine and I get back my pre-signed url. When I run this code on my front end:

postImage(uuid) {
    const getSignature = 'https://xyz.execute-api.us-east-1.amazonaws.com/dev/v1/createSignature';
    axios.get(getSignature)
    .then(res => {
        const signatureUrl = res.data.signedUrl;
        // I have a blob that I store in file
        // uuid is passed from another function
        const file = new File([this.state.cover], uuid);

        axios.post(signatureUrl, file)
        .then(s3Res => {
            console.log(s3Res);
        });
    });
}

The error I keep getting is: The request signature we calculated does not match the signature you provided. Check your key and signing method. I tried messing around with a few content-type headers but that did nothing. Can I pass the pre-signed url to a function in the aws-sdk? I've looked at a lot of posts on this but can't seem to resolve the issue.

1
Try axios.put(...) to use HTTP PUT rather than POST. - jarmod
Wow... that worked. Insane. Thank you so much!!! It seems like everywhere I was looking was using POST - user2465134

1 Answers

3
votes

When using pre-signed PutObject URLs for uploads to S3, you should upload files using the HTTP PUT method, rather than the HTTP POST method. You can POST objects to S3 but that's designed for browser-based uploads.