Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

why return base64 encoded? #99

Closed
goldenbearkin opened this issue Sep 26, 2017 · 11 comments
Closed

why return base64 encoded? #99

goldenbearkin opened this issue Sep 26, 2017 · 11 comments

Comments

@goldenbearkin
Copy link

goldenbearkin commented Sep 26, 2017

Hi,

If I understand correctly from #64 and #66 that listing 'application/json' in the binaryMimeTypes is for gzip support.

I tried to mimic the example with a simpler version. However I got the base64 encoded return.
Below is the setting for lambda.js and app.js

// lambda.js
'use strict'
const awsServerlessExpress = require('aws-serverless-express')
const app = require('./app')

// NOTE: If you get ERR_CONTENT_DECODING_FAILED in your browser, this is likely
// due to a compressed response (e.g. gzip) which has not been handled correctly
// by aws-serverless-express and/or API Gateway. Add the necessary MIME types to
// binaryMimeTypes below, then redeploy (`npm run package-deploy`)
const binaryMimeTypes = [
  'application/javascript',
  'application/json',
  'application/octet-stream',
  'application/xml',
  'font/eot',
  'font/opentype',
  'font/otf',
  'image/jpeg',
  'image/png',
  'image/svg+xml',
  'text/comma-separated-values',
  'text/css',
  'text/html',
  'text/javascript',
  'text/plain',
  'text/text',
  'text/xml'
]
const server = awsServerlessExpress.createServer(app, null, binaryMimeTypes)

exports.handler = (event, context) => awsServerlessExpress.proxy(server, event, context)
// app.js
'use strict'
const express = require('express')
const bodyParser = require('body-parser')
const cors = require('cors')
const compression = require('compression')
const awsServerlessExpressMiddleware = require('aws-serverless-express/middleware')
const app = express()


app.use(compression())
app.use(cors())
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))
app.use(awsServerlessExpressMiddleware.eventContext())

app.get('/testing', function (req, res) {
  res.json({testing: 'testing'})
})

module.exports = app

I got return value of
eyJ0ZXN0aW5nIjoidGVzdGluZyJ9
instead of
{testing: 'testing'}

@goldenbearkin
Copy link
Author

For those who's struggling the useage of binaryMimeTypes, here is my sharing. Please correct me if anything wrong.

The whole thing of adding MIME types to binaryMimeTypes is for compression. e.g. you want to gzip the application/json payload. let's first quote from @brettstack :

"Express response -> compression/gzip middleware (if you use it) -> aws-serverless-express (encodes to base64 if content-type is specified in binaryMimeTypes in Lambda handler) -> API Gateway (decodes base64 if content-type matches a binary mime type specified on API) -> Client"

here is my little supplement for his quote.

  1. Lambda doesn't support binary type, so aws-serverlesss-express needs to encode the compression to base64
  2. API gateway doesn't support gzip, but support binary type, so what it does is to let the express middleware do the compression, and decodes the base64 encoded payload received from lambda and finally pass to client.

@brettstack
Copy link
Collaborator

brettstack commented Sep 26, 2017 via email

@richburdon
Copy link

@goldenbearkin I'm having what seem to be encoding problems service PNG image files and thought this might be related. Did you run into this -- and if so, how did you solve it? Thanks.

@mikestead
Copy link

Just ran into this too. I noticed that API Gateway now supports compressing response bodies which means I think you can drop this workaround.

@sudosean
Copy link

sudosean commented Jan 9, 2019

I am working behind some gateway that is external to aws. Is there a way to turn of the base64 encoding?

@rsibanez89
Copy link

@brettstack would be awesome if we can disable the base64 encoding and return just a json.
Is there a way to do that?

@udonmai
Copy link

udonmai commented May 12, 2020

@goldenbearkin as you mentioned in API Gateway (decodes base64 if content-type matches a binary mime type specified on API) -> Client

I am assuming if we set binary mime types correctly in API gateway, the matching types of response will be decoded from base64 to its origianl format, while I tried to set */* and it's not working. I still get base64 format for even html file.

Any thoughts?

@shide1989
Copy link

What's the best practice so far ? I just created a new serverless express lambda, and all I get from the API is an base64 encoded string.

Shouldn't Amplify API automatically handle this ?

@aalaap
Copy link

aalaap commented Jan 31, 2021

I ran into this problem and realized that res.render() calls would render fine in the browser, but anything with express.static() would show up base64'd. I simply had to add the same binary types from lambda.js into my SAM template, somewhat like this:

Resources:
  ExpressServer:
    Type: AWS::Serverless::Api
    Properties:
      ...
      BinaryMediaTypes:
        - application~1javascript
        - application~1json
        ...
        - text~1xml

and Bob is now my uncle.

@softmarshmallow
Copy link

@goldenbearkin how did you fixed it?

@softmarshmallow
Copy link

Solution: Adding */* in aws console did the trick
image

Don't forget to re-deploy after changing the config

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants