al3x5
By:
al3x5

XMLHttpRequest file upload to Spaces fails due to CORS issue

November 15, 2017 224 views
API Python Storage Ubuntu

I'm trying to upload a file to Spaces using XMLHttpRequest with a pre-signed url generated by the boto3 Python library. I'm using the v2 signature type as the AWS v4 signature is not supported (yet). (https://www.digitalocean.com/community/questions/signed-urls-for-private-objects-in-spaces)

Performing an upload from the command line using the pre-signed url is working fine. However when doing a PUT request through an XMLHttpRequest object in Javascript I'm getting an CORS related error ("No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://XXX' is therefore not allowed access")

I have enabled CORS policies for this particular host like this:

<CORSConfiguration>
    <CORSRule>
        <AllowedOrigin>http://XXX</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

The preflight OPTIONS http request actually returns the appropriate headers like this:

Access-Control-Allow-Headers:content-type
Access-Control-Allow-Methods:PUT
Access-Control-Allow-Origin:http://XXX
Content-Length:0
Date:Wed, 15 Nov 2017 15:41:08 GMT
Strict-Transport-Security:max-age=15552000; includeSubDomains; preload
Vary:Origin
x-amz-request-id:tx000000000000003236214-005a0c6014-7ded-ams3a

In the actual PUT request which upload the file payload the headers returned by the Digital Ocean does not return the required Acces-Control-Allow-Origin header though:

Accept-Ranges:bytes
Content-Length:187
Content-Type:application/xml
Date:Wed, 15 Nov 2017 15:41:08 GMT
Strict-Transport-Security:max-age=15552000; includeSubDomains; preload
x-amz-request-id:tx00000000000000323b494-005a0c6014-ae42-ams3a

This finally results in a 403 Forbidden error. I'm really in the dark on this one, any insight would be highly appreciated..

4 Answers

It is simple to solve! Just use 's3cmd' command line tool:

s3cmd setcors file-with-bucket-cors.xml s3://BUCKETNAME

It is one shot config, after this, all will work perfectly!

Good luck!

Unfortunately it's not working. I wasn't aware of the s3cmd command but that seems to work too. I managed to set CORS policies before using the Boto3 Python library. The strange this is, the preflight OPTIONS request is actually returning the appropriate headers but things go wrong upon the upload PUT request. It sounds like some kind of server misconfiguration at DigitalOcean to me as uploading from command line works perfectly, although this doesn't require CORS headers to be returned. I created a ticket at DigitalOcean and they keep telling me to be patient but it's been about two weeks now and I'm losing confidence :-/

@al3x5 we just(yesterday) shipped a UI for CORS config in the DO Control Panel. Please take a look and if you are still running into challenges, let us know. Thanks for all of the feedback.

  • @johngannon thanks for letting me know. I noticed the appropriate CORS policies were already added (I did this by means of the Boto3 library) so they seemed correct al the time. However something goes wrong upon file upload. The preflight OPTIONS request does return the Access-Control-Allow headers, but once the actual PUT / upload request is done, headers are not returned which results in an error. I have opened a ticket for this issue (#777444) as well, to me this looks like some kind of server misconfiguration. Using the exact same upload routine through Amazon S3 does return the headers in the PUT request like this:

    Access-Control-Allow-Credentials:true
    Access-Control-Allow-Methods:GET, PUT, POST
    Access-Control-Allow-Origin:http://XXX.127.0.0.1.xip.io
    Access-Control-Expose-Headers:ETag, Date
    Access-Control-Max-Age:3000
    Content-Length:0
    Date:Wed, 06 Dec 2017 15:57:29 GMT
    ETag:"7c99e14bd72052c3749c6b0d6e6a36eb"
    Server:AmazonS3
    Vary:Origin, Access-Control-Request-Headers, Access-Control-Request-Method
    x-amz-id-2:/kO8g2n50bollNhMm/Z/xMkchm2V8v7Rq9jiYjYu8m/DhYUmfdKlAlovjFpNgdnrPimIPiJNB44=
    x-amz-request-id:147FA2431BD985D4

  • Ok, this was frustrating.. My reply was rejected as spam (?!) I lost my whole message..

    Anyhow, thanks for letting me know. I noticed the required CORS headers were already present in the Control Panel, I added them using the Boto3 library. Unfortunately I'm still running into errors though. As I mentioned earlier, the preflight OPTIONS request is returning the Access-Control-Allow headers, but they're missing in the actual upload / PUT request. It looks like some kind of server misconfiguration to me. Using the exact same upload routine with Amazon S3 does return the headers in the PUT request. Apparently I can't paste these headers as an example because my message will be rejected as spam again. But they should be returned by the server in order to complete the actual upload request successfully.

@al3x5 thanks Can you email me (jgannon @ do dot co) with all of the details that I would need to pass on to our engineering team? I want to make sure they have a full picture of what you're experiencing. Thanks for taking the time to give this feedback.

Have another answer? Share your knowledge.