Matsimitsu

Upload a file to an AWS pre-signed S3 url with RestClient.


Upload a file to a pre-signed url with Rest-Client.

You’d think that’s an easy task, just call:

RestClient.post(url, File.new(path, "rb"))

And call it a day, but this will leave you with cryptic error messages such as:

The request signature we calculated does not match the signature you provided.
Check your key and signing method.

There are two things we need to change, first is that Amazon taks the term putObject very literal, upload a file with the POST method will generate the error above.

RestClient.put(url, File.new(path, "rb"))

Changing the method to put will clear the cryptic signature error, but you’ll notice that any file uploaded will be corrupt. This because RestClient uploads the file as multipart/form-data, which is not recognised as a binary file by AWS.

To fix this provide a content-type header to RestClient, for example.

  RestClient.put(
    url,
    File.new(path, "rb"),
    :headers => {:content_type => "application/octet-stream"}
  )

In my case I was uploading images and this worked for me:

  RestClient.put(
    url,
    File.new(path, "rb"),
    :headers => {:content_type => "image/jpeg"}
  )

Hopefully this will save someone else an hour of debugging AWS request signature calculations :)

More posts


Tailwind CLI with Yew and Trunk

Let's see if we can go node-less with Yew.

Serving static CORS JSON with Caddy

For a simple side-project, I needed to serve static JSON, with proper CORS headers.

Switching to Svelte

I have rewritten my middleman site to Svelte/SvelteKit, here's what I encountered.

Remote uploads with pre-signed URLs on Scaleway's object storage.

Or, make sure your headers match, otherwise you'll get a lot of strange errors.

Upload a file to an AWS pre-signed S3 url with RestClient.

Or, how something so simple cost me so much time.