serverless-apigw-binary icon indicating copy to clipboard operation
serverless-apigw-binary copied to clipboard

How to prevent application/json being transformed into base64

Open benoj opened this issue 7 years ago • 7 comments

I have a serverless app which uploads files to s3 (via POST request) and serves them (via GET request)

In order to upload an image the POST endpoint takes a body like { "base64": "..." }. However with this configuration the entire body is coming through as a base64 encoded string. How can I prevent the request body with application/json being transformed?

See serverless.yml below:

service: image-service

custom:
  envName: ${opt:stage, self:provider.stage}
  domains:
    prod: api.<mydomain>
    dev: dev-api.<mydomain>
  customDomain:
    basePath: images
    domainName: ${self:custom.domains.${self:custom.envName}}
    certificateName: "*.<mydomain>"
  apigwBinary:
    types:
      - '*/*'
      
provider:
  name: aws
  runtime: nodejs8.10
  region: eu-west-1
  memorySize: 1536

  role: ImageRenderingRole

  environment:
    ENV_NAME: ${self:custom.envName}
    APP_NAME: image-service
    BUCKET: <mybucket>

plugins:
  - serverless-offline
  - serverless-domain-manager
  - serverless-apigw-binary
  - serverless-apigwy-binary

functions:
 uploadImage:
   handler: handler.uploadImage
   events:
     - http:
      path: /
      method: POST

  getImage:
    handler: handler.getImage
    events:
      - http:
          path: 'images/{idAndFormat}'
          method: get
          contentHandling: CONVERT_TO_BINARY
          parameters:
              paths:
                idAndFormat: true

This is a clone of (https://stackoverflow.com/questions/52479994/serverless-api-gateway-transforming-request-into-base64) but no response as of yet...

benoj avatar Sep 25 '18 07:09 benoj

I also have this same question. After adding this plugin all of my incoming responses are being transformed to base64 even if I set the content type to application/json. I only want to use base64 for one endpoint and I don't think the right answer is to just decode everything.

brian-fivetalent avatar Jul 16 '19 03:07 brian-fivetalent

That was just a lack of understanding on my part. this will convert any Content-Type that matches whats provided here to binary. If you don't want application/json converted to binary, don't list it there.

  apigwBinary:
    types:
      - '*/*'

brian-fivetalent avatar Jul 16 '19 03:07 brian-fivetalent

@brian-fivetalent did setting a specific type work for you in the end? I'm having the same problem even if i use: apigwBinary: types: - 'image/png'

PavelYaroshchyk avatar Jul 09 '20 13:07 PavelYaroshchyk

Same here, no matter what I list everything gets the CONVERT_TO_BINARY. Kind of annoying since I don't want my error messages to be mp3s :-)

fsvaren avatar Aug 05 '20 17:08 fsvaren

fcking serverlesss of st I can't download f*cking file!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

joneldiablo avatar Apr 06 '21 23:04 joneldiablo

Same issue, and doing below does NOT resolve:

  apigwBinary:
    types:
      - 'image/png' # or any other format

pomSense avatar Sep 08 '21 07:09 pomSense

After some fiddling around, I was able to resolve this issue. Here are my findings:

  • If you add */* under types, this means that ALL request events will be converted to binary. As mentioned by @brian-fivetalent , first you have to list only the types you want as binary
  • If you have already deployed, then APIGW has already but the wildcard */* as Binary Media Types. Even if you remove this, the plugin doesn't remove it from APIGW. You have to MANUALLY go to APIGW > your_api > settings > Binary Media Types and delete the wildcard there: Screen Shot 2021-09-08 at 1 36 17 AM
  • Click Save and them deploy

Here is how my serverless.yml is setup with the plugin:

...

plugins:
  - serverless-webpack
  - serverless-deployment-bucket
  - serverless-apigateway-service-proxy
  - serverless-apigw-binary
  - serverless-offline

custom:
  apigwBinary:
    types: 
    # Only add Content-Types here that you want to convert as Binary. 
    # Note, this will happen for ALL end-points. 
    # Don't add */* or else it will convert all paths and functons' requests to binary.
      - 'multipart/form-data'

functions:
  myFunction:
    handler: src/infra/http/index.myFunction
    events:
      - http:
          path: myPath
          method: post
          cors: true
          request:
            parameters:
              paths:
                myPathParam: true

I am only using serverless-apigw-binary and not serverless-apigwy-binary

Hope this helps!

pomSense avatar Sep 08 '21 08:09 pomSense