I am experimenting running the aws-serverless-express module in combination with the serverless-offline plugin for the serverless framework. This combination results in a critical error upon sending the request to the corresponding path and not when the serverless offline start command is run. Testing the offline plugin with another route not using the aws-serverless-express module runs fine and gives me a response. This is what I have:
{
"name": "ExpresssLambdaServerless",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"aws-serverless-express": "^3.0.2",
"express": "^4.16.2"
},
"devDependencies": {
"serverless-offline": "^3.16.0"
}
}
service: aws-nodejs
provider:
name: aws
runtime: nodejs6.10
functions:
helloExpress:
handler: index.handlerExpress
events:
- http: GET express
helloPlain:
handler: index.handlerPlain
events:
- http: GET plain
plugins:
- serverless-offline
'use strict';
const awsServerlessExpress = require('aws-serverless-express');
const app = require('./app');
const server = awsServerlessExpress.createServer(app);
// does NOT work
exports.handlerExpress = (event, context, callback) => awsServerlessExpress.proxy(server, event, callback);
// works
exports.handlerPlain = (event, context, callback) => {
callback(null, {
statusCode: 200,
body: JSON.stringify({
works: true
})
});
};
'use strict';
const express = require('express');
const awsServerlessExpressMiddleware = require('aws-serverless-express/middleware');
const app = express();
app.get('/express', (req, res) => {
res.status(200).json({
works: false
});
});
module.exports = app;
v8.9.0$ sls offline start
Serverless: Starting Offline: dev/us-east-1.
Serverless: Routes for helloExpress:
Serverless: GET /express
Serverless: Routes for helloPlain:
Serverless: GET /plain
Serverless: Offline listening on http://localhost:3000
Serverless: GET /plain (位: helloPlain)
Serverless: The first request might take a few extra seconds
Serverless: [200] {"statusCode":200,"body":"{\"works\":true}"}
Serverless: GET /express (位: helloExpress)
Serverless: The first request might take a few extra seconds
ERROR: server error
{ Error: listen EACCES /tmp/server0.sock
at Object._errnoException (util.js:1024:11)
at _exceptionWithHostPort (util.js:1046:20)
at Server.setupListenHandle [as _listen2] (net.js:1334:19)
at listenInCluster (net.js:1392:12)
at Server.listen (net.js:1487:5)
at startServer (my-pc-path\node_modules\aws-serverless-express\index.js:136:19)
at Object.proxy (my-pc-path\node_modules\aws-serverless-express\index.js:175:16)
at exports.handlerExpress (my-pc-path\index.js:7:67)
at handler (my-pc-path\node_modules\serverless-offline\src\index.js:751:25)
at Object.internals.handler (my-pc-path\node_modules\hapi\lib\handler.js:96:36)
at request._protect.run (my-pc-path\node_modules\hapi\lib\handler.js:30:23)
at module.exports.internals.Protect.internals.Protect.run (my-pc-path\node_modules\hapi\lib\protect.js:64:5)
at exports.execute (my-pc-path\node_modules\hapi\lib\handler.js:24:22)
at each (my-pc-path\node_modules\hapi\lib\request.js:384:16)
at iterate (my-pc-path\node_modules\items\lib\index.js:36:13)
at done (my-pc-path\node_modules\items\lib\index.js:28:25)
at module.exports.internals.Auth.internals.Auth._authenticate (my-pc-path\node_modules\hapi\lib\auth.js:210:16)
at internals.Auth.authenticate (my-pc-path\node_modules\hapi\lib\auth.js:202:17)
at each (my-pc-path\node_modules\hapi\lib\request.js:384:16)
at iterate (my-pc-path\node_modules\items\lib\index.js:36:13)
at done (my-pc-path\node_modules\items\lib\index.js:28:25)
at internals.state (my-pc-path\node_modules\hapi\lib\route.js:357:16)
at each (my-pc-path\node_modules\hapi\lib\request.js:384:16)
at iterate (my-pc-path\node_modules\items\lib\index.js:36:13)
at Object.exports.serial (my-pc-path\node_modules\items\lib\index.js:39:9)
at internals.Request._lifecycle (my-pc-path\node_modules\hapi\lib\request.js:387:11)
at internals.Request._execute (my-pc-path\node_modules\hapi\lib\request.js:302:21)
at Domain.request._protect.enter (my-pc-path\node_modules\hapi\lib\connection.js:261:25)
at Domain.run (domain.js:242:14)
at module.exports.internals.Protect.internals.Protect.enter (my-pc-path\node_modules\hapi\lib\protect.js:80:17)
at Server.<anonymous> (my-pc-path\node_modules\hapi\lib\connection.js:259:30)
at emitTwo (events.js:126:13)
at Server.emit (events.js:214:7)
at parserOnIncoming (_http_server.js:602:12)
at HTTPParser.parserOnHeadersComplete (_http_common.js:117:23)
code: 'EACCES',
errno: 'EACCES',
syscall: 'listen',
address: '/tmp/server0.sock',
port: -1 }
I tried running the serverless-offline plugin on a different port as well with the same result. My assumption is that both the serverless plugin and the aws-serverless-express modules are creating a server using the same resource and this is why it breaks when the express endpoint is called. I also tried changing the tmp path in index.js file of aws-serverless-express to something different, but didn't work either.
I would highly appreciate some help. PM me if more info is needed. Thanks!!!
I'm having the same issue, some help would be greatly appreciated!
@dpapukchiev There is a fix for this in this pull request: https://github.com/awslabs/aws-serverless-express/pull/100. However it has not yet been merged. The first call with this will succeed but additional calls will fail.
+1
+1
+1
I think _socketPathSuffix should be random value instead of incrementing number. cf. #5
I created a randomized suffix version https://github.com/y13i/aws-serverless-express/tree/feat-randomized-sock-suffix just for test purpose and you can test it with npm install @y13i/aws-serverless-express.
Should I send a pull request with that version?
@y13i Please and thank you.
// it doesn't take the ```callback``` object, you should use instead ```context```
awsServerlessExpress.proxy(server, event, callback) // not working
awsServerlessExpress.proxy(server, event, context ) // working
but then, another problem will occur when testing on localhost
here is a way to fix the second problem.
call this function BEFORE require('aws-serverless-express') in your handler file.
function path_part_1(){
if( process.env.IS_OFFLINE){
process.env.NODE_ENV = 'test // awsServerlessExpress make available it's api only web it is set to 'test'
}
}
then, in order to clean up your tmp
call this function AFTER require('aws-serverless-express') and BEFORE calling awsServerlessExpress.createServer
function path_part_1(){
if( process.env.IS_OFFLINE){
let fs = require('fs')
let createServer = awsServerlessExpress.createServer
awsServerlessExpress.createServer = (server)=>{
let awsExpressServer = createServer( server )
let tmp_path = awsServerlessExpress.getSocketPath(awsExpressServer._socketPathSuffix)
if( fs.existsSync(tmp_path) ) { fs.unlinkSync( tmp_path ) }
return awsExpressServer
}
}
}
Fixed in 3.1.1
Most helpful comment
Fixed in 3.1.1