I use aws-serverless-express/middleware but can't get the API Gateway event object.
Here is my code.
...
import awsServerlessExpress from 'aws-serverless-express';
import awsServerlessExpressMiddleware from 'aws-serverless-express/middleware';
...
const app = express();
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
api.use(awsServerlessExpressMiddleware.eventContext());
app.use('/', api);
const server = awsServerlessExpress.createServer(app);
exports.handler = (event, context) => awsServerlessExpress.proxy(server, event, context);
When i use access req.apiGateway.event, error has occurred like below.
TypeError: Cannot read property 'event' of undefined
Am i missing something? or is this bug?
api.use(awsServerlessExpressMiddleware.eventContext());
app.use('/', api);
Where is api defined? Why not just:
app.use(awsServerlessExpressMiddleware.eventContext());
Which is how you're defining your other middleware.
@brettstack
Sorry for confusing.
I import my router like this.
import api from './router';
and also i tried to
api.use(awsServerlessExpressMiddleware.eventContext());
and
app.use(awsServerlessExpressMiddleware.eventContext());
but both did't work.
Shouldn't you be defining all your middleware the same way though? See our example here:
https://github.com/awslabs/aws-serverless-express/blob/master/examples/basic-starter/app.js#L21
@brettstack
Right. Anyway, all other middleware except this are work well. And all router is works well too only except some router using req.apiGateway.
eventContext() function doses't make an error but req.apiGateway object is undefined. It is very weird.
What I'm suggesting is try to change all of your other middleware to use api.use.
Just to make sure: are you running this locally or in Lambda? If it's local, you'll need to do some additional work to get the middleware to work.
Also, try logging console.log(JSON.stringify(req.headers, null, 4)) and seeing if 'x-apigateway-event' is present.
@brettstack
x-apigateway-event' is present but req.apiGateway is still undefined In lambda.
I think I'm going to need to see more code. Specifically, the route where you're trying to access req.headers and req.apiGateway.
As you can see, the middleware is very simple https://github.com/awslabs/aws-serverless-express/blob/master/src/middleware.js#L6. If x-apigateway-event is present and req.apiGateway is not, then it seems like the middleware isn't being run. Have you tried what I suggested before?
What I'm suggesting is try to change all of your other middleware to use api.use
@brettstack
yes. I tried to what you said.
Here is my code.
// app.js
import express from 'express';
import awsServerlessExpress from 'aws-serverless-express';
import awsServerlessExpressMiddleware from 'aws-serverless-express/middleware';
import bodyParser from 'body-parser';
import cors from 'cors';
import api from './router';
import { sequelize } from './db';
import { sync } from './db/sync';
const app = express();
app.use(cors());
api.use(bodyParser.json());
api.use(bodyParser.urlencoded({ extended: true }));
api.use(awsServerlessExpressMiddleware.eventContext());
sequelize.authenticate().then(() => {
sync();
});
app.use('/', api);
if (process.env.NODE_ENV === 'development') {
app.listen(8080, () => {
console.log(`Express server listening on port 8080`);
});
}
const server = awsServerlessExpress.createServer(app);
exports.handler = (event, context) => awsServerlessExpress.proxy(server, event, context);
// router
export const uploadBookCoverImage = (req, res) => {
console.log(JSON.stringify(req.headers, null, 4));
console.log(req.apiGateway);
let imgFile = req.file;
res.json(imgFile);
};
Did you manage to solve your issue?
No. I didn't...
I found queryStringParameters, pathParameters, stageVariables, requestContext all get passed to the lambda function inside req.headers['x-apigateway-event'] by the proxy API Gateway
I found solution for similar problem in a comment here: https://stackoverflow.com/a/42441810/747834
"app.use(awsServerlessExpressMiddleware.eventContext())" must be done before any "app.use('/', index);"
In case any other lost souls who are encountering Missing x-apigateway-event or x-apigateway-context header(s) when doing local testing (e.g. from Postman) find their way here... You have to set both of the x-apigateway-event and x-apigateway-context headers in Postman. The important thing is their values have to be
encodeURIComponent(JSON.stringify({"example": "data here" }));
So for instance, if the header key is:
x-apigateway-event
Then the value should be
%7B%22data%22%3A%22Sand%22%2C%22public_key%22%3A%22key%22%7D
Note, there are no quotes around the encoded and stringified value!
You have to set both x-apigateway-event and x-apigateway-context headers because if you peek in your node_modules/aws-serverless-express/src/middleware.js file you'll see it has the following lines:
if (!req.headers['x-apigateway-event'] || !req.headers['x-apigateway-context']) {
next()
return
}
req[reqPropKey] = {
event: JSON.parse(decodeURIComponent(req.headers['x-apigateway-event'])),
context: JSON.parse(decodeURIComponent(req.headers['x-apigateway-context']))
}
Most helpful comment
In case any other lost souls who are encountering
Missing x-apigateway-event or x-apigateway-context header(s)when doing local testing (e.g. from Postman) find their way here... You have to set both of thex-apigateway-eventandx-apigateway-contextheaders in Postman. The important thing is their values have to beSo for instance, if the header key is:
x-apigateway-eventThen the value should be
%7B%22data%22%3A%22Sand%22%2C%22public_key%22%3A%22key%22%7DNote, there are no quotes around the encoded and stringified value!
You have to set both
x-apigateway-eventandx-apigateway-contextheaders because if you peek in yournode_modules/aws-serverless-express/src/middleware.jsfile you'll see it has the following lines: