CodeGenieApp / serverless-express

Run Express and other Node.js frameworks on AWS Serverless technologies such as Lambda, API Gateway, Lambda@Edge, and more.
https://codegenie.codes
Apache License 2.0
5.15k stars 669 forks source link

res.sendFile returning different results when run locally vs in Lambda #55

Closed JensenTStava closed 6 years ago

JensenTStava commented 7 years ago

The below code returns different results based on running it locally vs running it on Lambda. Locally this returns a javascript file properly formatted. However, when I deploy to Lambda I get a base64 encoded blob that is not readable by my application. I have this set up as a proxy integration with API gateway, so it should not be altering the payload at all, and yet it is. Why is this library (or lambda) forcing a base64 encoded response?

'use strict'
const path = require('path')
const compression = require('compression')
const express = require('express')
const bodyParser = require('body-parser')
const cors = require('cors')
const awsServerlessExpressMiddleware = require('aws-serverless-express/middleware')
const app = express()

app.set('view engine', 'pug')
app.use(compression())
app.use(cors())
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))
app.use(awsServerlessExpressMiddleware.eventContext())

app.get('/widget/:widgetId', (req, res) => {
    console.log(req)
    res.setHeader('Content-Type', 'text/javascript')
    res.sendFile(path.join(__dirname, '/widget/bundle.js'), {}, function (err) {
        if(err) {
            console.log(err)
        } else {
            console.log("no error")
        }
    })
})

// app.listen(3000, function () {
//   console.log('Example app listening on port 3000!')
// })

module.exports = app
brettstack commented 7 years ago

Ensure you have text/javascript configured in your API Gateway API as a binary media type https://github.com/awslabs/aws-serverless-express/blob/master/example/simple-proxy-api.yaml#L98

JensenTStava commented 7 years ago

Is there a way to do that in the AWS UI?

brettstack commented 7 years ago

Yes, click on your API and then click Binary Support

On Fri, Mar 31, 2017, 7:18 PM JensenTStava notifications@github.com wrote:

Is there a way to do that in the AWS UI?

— You are receiving this because you commented.

Reply to this email directly, view it on GitHub https://github.com/awslabs/aws-serverless-express/issues/55#issuecomment-290887135, or mute the thread https://github.com/notifications/unsubscribe-auth/ABy6lxyeV5NI_PWEwWU-YYMSQU8uORvNks5rrbQKgaJpZM4MwOxB .

JensenTStava commented 7 years ago

I have tried that. It doesn't convert the output back to non-base64

brettstack commented 7 years ago

Did you redeploy your API after setting that?

On Fri, 31 Mar 2017 at 19:47 JensenTStava notifications@github.com wrote:

I have tried that. It doesn't convert the output back to non-base64

— You are receiving this because you commented.

Reply to this email directly, view it on GitHub https://github.com/awslabs/aws-serverless-express/issues/55#issuecomment-290888850, or mute the thread https://github.com/notifications/unsubscribe-auth/ABy6l0O3XB06kFItqvKlUhpiVMQG3ohTks5rrbq9gaJpZM4MwOxB .

JensenTStava commented 7 years ago

Yes. I have tried everything apparent... been troubleshooting for 4 hours. Is there should me Lambda configuration that isn't apparent?

brettstack commented 7 years ago

Only this https://github.com/awslabs/aws-serverless-express/blob/master/example/lambda.js#L23

JensenTStava commented 7 years ago

I already have that represented when creating the express server:

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

const binaryMimeTypes = [ 'text/javascript' ] const server = awsServerlessExpress.createServer(app, null, binaryMimeTypes)

exports.handle = (event, context) => { console.log("event: " +JSON.stringify(event)) console.log("context: "+ JSON.stringify(context)) awsServerlessExpress.proxy(server, event, context) }`

The data is being returned as text/javascript, it is just base64 encoded...

JensenTStava commented 7 years ago

Ok. I found the problem. I am using Apex to deploy my code and it seems that there is a requirement to use exports.handle as opposed to exports.handler. But module.exports = app in my express app is not resolving back to exports.handle. Is there a way that I can address this?

brettstack commented 7 years ago

In your lambda.js you can do exports.handle = app.

On Mon, Apr 3, 2017, 11:43 AM JensenTStava notifications@github.com wrote:

Ok. I found the problem. I am using Apex to deploy my code and it seems that there is a requirement to use exports.handle as opposed to exports.handler. But module.exports = app in my express app is not resolving back to exports.handle. Is there a way that I can address this?

— You are receiving this because you commented.

Reply to this email directly, view it on GitHub https://github.com/awslabs/aws-serverless-express/issues/55#issuecomment-291235643, or mute the thread https://github.com/notifications/unsubscribe-auth/ABy6l6cU31FWK-BfyTLU4061o5WX5b0Iks5rsT3qgaJpZM4MwOxB .

JensenTStava commented 7 years ago

When I make that change I get the following error:

Error: function response: "listener" argument must be a function

Upon looking at this further, I cannot understand why this would be returning data at all if the export was misconfigured. The problem is not that my routes are not being respected, it is that the data being returned from my express app is being altered buy Lambda, or this library. Does aws-serverless-express encode the data before sending it to the calling service?

kahouieong commented 7 years ago

This library will decode the data from API Gateway and pass in your express application, then encode the data before return it to API Gateway.

brettstack commented 7 years ago

@JensenTStava did you resolve this? You could try modifying your API Gateway API Binary types to include */* and then redeploy.