serverless-application-model icon indicating copy to clipboard operation
serverless-application-model copied to clipboard

BinaryMediaTypes and CORS do not work together

Open espenjanson opened this issue 5 years ago • 12 comments

We cannot get CORS to work with BinaryMediaTypes

Error message:


OPTIONS https://URL 500

Access to XMLHttpRequest at 'https://URL' from origin 'http://localhost:8000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access- 
Control-Allow-Origin' header is present on the requested resource.

This is our sam template:


Resources:
  ApiName:
    Type: AWS::Serverless::Api
    Properties:
      StageName: development
      BinaryMediaTypes:
        - '*~1*'
      Cors:
        AllowMethods: "'*'"
        AllowHeaders: "'*'"
        AllowOrigin: "'*'"
      Auth:
        DefaultAuthorizer: CognitoAuthorizer
        AddDefaultAuthorizerToCorsPreflight: false
        Authorizers:
          CognitoAuthorizer:
            UserPoolArn: 'USER_POOL'

As soon as we remove the "BinaryMediaTypes" option, the request works.

SAM CLI, version 0.37.0

espenjanson avatar Dec 25 '19 10:12 espenjanson

Did you ever figure out the problem here? I'm having the same issue.

averydev avatar Jul 23 '20 02:07 averydev

I have the same issue, please somebody help us!!!

rcermeno avatar Oct 23 '20 17:10 rcermeno

@espenjanson @averydev I could solve it.

Just put the mime types you need in the BinaryMediaTypes property. i.e:

BinaryMediaTypes:
        - 'text~1html'
        - 'application~1xhtml+xml'
        - 'application~1xml;q=0.9'
        - 'image~1*'

The reason: If you set the property to * / *, then ApiGateway tries to convert all responses to Binary, even json responses, and throws an error.

rcermeno avatar Oct 23 '20 18:10 rcermeno

SAM should support content handling for CORS OPTIONS requests. For example in AWS::Serverless::Api Please add an option under the Cors: section to be able to convert to text so this binary problem is fixed. contentHandling: CONVERT_TO_TEXT

  Cors:
    AllowMethods: "'OPTIONS,HEAD,GET,POST,PUT,DELETE'"
    AllowHeaders: "'Access-Control-Request-Headers,Access-Control-Request-Method,Access-Control-Allow-Origin,x-api-key,Accept,Content-Type'"
    AllowOrigin: "'*'"
    contentHandling: CONVERT_TO_TEXT

danbanecker avatar Nov 04 '20 20:11 danbanecker

There are situations when it is necessary to specify

BinaryMediaTypes:
  - '*.*'

Because this is the "Accept" header that browsers and curl send and the BinaryMediaTypes must match it.

Unfortunately workaround suggested by @rcermeno does not help in this case. More discussion here: https://github.com/aws/aws-sam-cli/issues/312

marinaglancy avatar Jan 23 '21 14:01 marinaglancy

Is it possible to configure SAM to defer all CORS logic to the lambda proxy? Our lambda is implemented with flask, so dealing with CORS on that level isn't too bad.

We are setting BinaryMediaTypes to */* to work around a variety of issues. It worked beautifully until we realized it broke CORS.

hhowe29 avatar May 28 '21 14:05 hhowe29

any workaround to serve binaries (like when Content-Type is application/pdf) and not require "Accept" header in the request, while working with CORS?

luizwhite avatar Aug 17 '21 23:08 luizwhite

Having the same issue - damn I just thought I finally have a solution for handling binary files in the browser with the */* mediaType and then had to realize it broke CORS.

matzeso avatar Sep 06 '21 10:09 matzeso

I have a slightly different problem. I tried to upload files via Lamba to S3, its works only on the non-browser environment but not the browser.

Postman -> lambda (can upload - without cors) Browser -> lambda (can't upload)

I solved it by adding "multipart/form-data" to "Binary Media Types" or "BinaryMediaTypes".

I hope this comment can help someone in the future.

psudocode avatar Mar 16 '22 13:03 psudocode

4 years later, still troublesome

choutkamartin avatar Oct 02 '23 22:10 choutkamartin

I lost many hours to this. It doesn't help that the lambda powertools documentation example uses BinaryMediaTypes and CORS together. I copied this part thinking that these are "recommended" for lambda-powertools, I wonder now if that documentation example is wrong

Also it doesn't help that I tested locally using sam local start-api and there it works, but when it is deployed it does not work

martinber avatar Nov 20 '23 15:11 martinber

I also lost many hours trying to resolve this issue. Can anyone explain to me why API Gateway must look at the Accept header to encode/decode binary data? Wouldn't it be sufficient to simply look at the Content-Type request header and match it with BinaryMediaTypes for requests?

As I see it, ignoring the Accept header when making the decision to encode/decode binary data would solve this issue.

payros avatar Mar 21 '24 16:03 payros