Reputation: 119
I have recently come across a problem I have never seen or even heard of before. I am using an AWS HTTP API Gateway which is integrated with a simple lambda function that returns a response from a DB. Hardly rocket surgery. The problem is this; when I make a request the first time, the response comes back as it should, with the body as JSON.
When I make an identical request a few seconds later, the response looks like this:
And the third time, this:
It gets worse and worse each time. My function response follows the rules defined in the developer guide, and as you can see from the first response, it's working just fine.
Why it would escape multiple times after that is beyond me. In my lambda code, I stringify the JSON once response.body = JSON.stringify(response.body)
to follow the spec. There is nothing in my code that even knows to stringify multiple times based on an individual users IP address only after a certain number of requests within a certain timespan that go back to normal after a half hour or so.
Any help would be appreciated.
UPDATE:
index.js
const users = require ('./handlers/users.js')
const auth = require ('./lib/auth.js')
exports.handler = async (event) => {
const body = event.body ? JSON.parse(event.body) : undefined;
const queryString = event.queryStringParameters
const authHead = event.headers.authorization ? JSON.parse(event.headers.authorization) : undefined
const path = event.requestContext.http.path
const method = event.requestContext.http.method
const authUser = auth(authHead)
// I have more handlers, but you get the idea...
const handlers = {
'/users': {
POST: users.post,
PATCH: users.patch,
GET: users.get,
},
}
const response = await handlers[path][method](authUser, queryString, body)
response.body = JSON.stringify(response.body)
return response;
};
/handlers/users.js
const AWS = require('aws-sdk')
const docClient = new AWS.DynamoDB.DocumentClient()
const response = {
statusCode: 500,
body: {
message: 'unhandled error',
payload: undefined
}
}
exports.get = async (authUser, queryString, body) => {
const params = {
TableName: 'db-name',
Key: {
'PK': undefined,
'SK': undefined
}
}
if (queryString.id) {
params.Key.PK = queryString.id;
params.Key.SK = `user#${queryString.id}`;
} else if (queryString.username) {
params.IndexName = 'GSI'
params.ExpressionAttributeValues[':ID'] = queryString.username
} else {
response.statusCode = 400
response.body = { message: 'bad request', payload: undefined }
return response
}
try {
const results = await docClient.get(params).promise()
response.body.payload = results
response.statusCode = 200
response.body.message = 'success'
return response
}
catch (err) {
console.log(err)
response.statusCode = 400
response.body = 'failed'
return response
}
}
Upvotes: 2
Views: 546
Reputation: 3965
You defined response
as a const
global object:
const response = {
statusCode: 500,
body: {
message: 'unhandled error',
payload: undefined
}
}
Because in JavaScript, assignment is not object copy, and const object can be modified, when you modify response.body
, you're actually modifying the body
property of the global response
object.
To fix the issue: just move the const response = ...
assignment to inside the async (authUser, queryString, body) => { ... }
function. It will create a new object each time.
Upvotes: 2