Presigned_url with post - method not allowed

Hi Peops,

SO I am trying to use the “presign_url” method on the ex_aws_s3 package - which is essentially just the “ex_aws.Auth.presign_url”.

Long story short - regardless of what url I use or options… I just cannot get this function to play ball even with postman let alone trying to send data from the browser as a form object.

[https://imgur.com/zcRA3sm](response , headers and url1)

[https://imgur.com/TNeOHsD](response , headers and url2)

my function:


  def presign_post_url(bucket_name, file_name, file_type_extension) do                                            config = % 
     config = { region: "eu-west-1" }
     ex_s3_client = ExAws.Config.new(:s3, config)
     query_params = [
        { "Content-Type", "image/jpg"},                                                                               
        {'key', "profile-pictures/" <> file_name}                                                                     
        # { "content-length-range", "10\,10000000" }#max 10MB
     ]                                                                                                             
    presign_options = [virtual_host: false, query_params: query_params]                                                                                                                                                       
    
    ExAws.S3.presigned_url(ex_s3_client, :post, "profile-pictures", file_name, presign_options)                                                                                                                               
  end

The error I get - not matter how I construct the url with bucket_name/folder-path/differents3-url-structures, I always get:

<?xml version="1.0" encoding="UTF-8"?>
<Error>
    <Code>MethodNotAllowed</Code>
    <Message>The specified method is not allowed against this resource.</Message>
    <Method>POST</Method>
    <ResourceType>OBJECT</ResourceType>
    <RequestId>D0BA0AC513BE36D6</RequestId>
    <HostId>NyzdUPLDzHnbkHzWxxcLjdGXOXkpmGOUU1KFIAPJ+vpIPEq0WWyZEerGq1xySG26qzPfKUg7l/o=</HostId>
</Error>

Cors on bucket:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>

I am stumped, there’s another little issue - about getting the presign_url method to play nicely with “content-length-range”, as it’s not a two value keyword list.
Any help or advice would be awesome!

Hi @9Dave9, welcome to the forum! :smile:

I don’t know if using POST is a requirement for you, but I was coding a file upload recently and I’m able to PUT files using pre-signed URLs like bellow (and using axios.put to actually upload the file):

ExAws.Config.new(:s3) |>  ExAws.S3.presigned_url(:put, bucket_name(), upload_path())

My bucket CORS config:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
</CORSConfiguration>

I tried using POST myself at first, but it was tricky enough (I haven’t come back to test it again).

Hi @thiagomajesk,

yup I have this same solution currently. The reason I wanted to use POST instead of PUT is because AWS allow you define a max file size for upload on presigned_post requests. The presigned_put requests are pretty limited.

Currently calculating this on the handset and if it’s below the threshold I’ll approve the upload. But it’s hackable of course… would have preferred that this was a restriction encoded into the presigned url for client side use.

I decided to move on - I know it’s possible but I think the documentation aws side is making this a bit less so. heh

Thanks for the suggestion.

@9Dave9 Ok, I guess we are on the same boat then. I’m currently using the full 5GB limit though :sweat_smile:.
Both ex_aws and ex_aws_s3 are very raw regarding documentation on how to use the available APIs, so it can be really difficult if you don’t have previous knowledge of Amazon’s services and its idiosyncrasies (which are also not very documented sometimes).

Since this a very common use-case for file uploads, I’m surprised I couldn’t find better information. So, let’s agree to come back here if either one of us finds a better solution, deal?

1 Like

I ran into this exact issue and came across this set of posts from AWS: Browser-Based Uploads Using POST (AWS Signature Version 4) - Amazon Simple Storage Service.

Specifically from this post: Creating an HTML Form (Using AWS Signature Version 4) - Amazon Simple Storage Service

To allow users to upload content to Amazon S3 by using their browsers (HTTP POST requests), you use HTML forms

Luckily, there’s a presigned_post util ex_aws_s3 specifically for this.