So I want the response body to be empty. I tried varionations of the following:
export const hello = async (event, context, callback) => {
callback(null, null)
}
However this returns a string 'null'.
If I don't invoke the callback lambda responds with a timeout error or something.
callback is expecting an HTTP response object in second argument. Try like this.
exports.handler = async (event, context, callback) => {
callback(null, {
statusCode: '200',
body: ''
});
};
Related
I have a lambda function that returns a message to the client.
function replyToMessage (messageText,connectionId) {
const data = {message:messageText}
const params = {
ConnectionId : connectionId,
Data: Buffer.from(JSON.stringify(data))
}
return api.postToConnection(params).promise()
.then(data => {})
.catch(error => {console.log("error",error)})
}
This code is called once when the connection is made and I get a response to my client. When I call the function again with a different endpoint, it doesn't send a response to my client. However, when I call it a third time, I get the response to my client from the second call. Here's my switch when the Lambda function is called.
switch(route) {
case "$connect":
break
case "$disconnect":
break
case "connectTo":
await connectToService(JSON.parse(event.body).eventId,connectionId)
await replyToMessage("Connected eventId to connId",connectionId)
break
case "disconnectFrom":
await disConnectToService(JSON.parse(event.body).eventId,connectionId)
break
case "project":
responseItems = await getBroadcastIds (JSON.parse(event.body).eventId,JSON.parse(event.body).sourceId,connectionId)
console.log(responseItems)
responseItems.Items.forEach(async function(item) {
await replyToMessage(JSON.parse(event.body).sourceId,item.connectionId)
})
responseItems = []
break
default :
console.log("Unknown route", route)
The issue appears to be the async forEach loop. Switching to the following resolves the issue.
for (const item of responseItems.Items) {
console.log("Sending to:",item.connectionId);
await replyToMessage(JSON.parse(event.body).sourceId,item.connectionId)
}
See this post for the answer that led to this resolution. Using async/await with a forEach loop
I'm trying to use the v3 javascript sdk to invoke a AWS Lambda function, and I'm having problems getting any meaningful response.
My code looks like so...
const { Lambda } = require("#aws-sdk/client-lambda");
const client = new Lambda();
const params = {
FunctionName: "MyLamdaFuncton",
Payload: JSON.stringify({ "action": "do_something" }),
InvocationType: "Event"
};
client.invoke(params)
.then((response) => {
console.log(JSON.stringify(response,null,4));
})
.catch((err) => {
console.error(err);
})
I can confirm from checking the CloudWatch logs that the lambda function works as exepcted. However this is the response I get in my NodeJS code...
{
"$metadata": {
"httpStatusCode": 202,
"requestId": "d6ba189d-9156-4f01-bd51-efe34a66fe34",
"attempts": 1,
"totalRetryDelay": 0
},
"Payload": {}
}
How do I get the actual response and status from the Lambda function?
If I change the payload above to intentionally throw an exception in my Lambda, the response in the console is still exactly the same.
update:
The Lambda function is written in Ruby. The response is returned like so...
{ statusCode: 200, body: JSON.generate(response.success?) }
where "response" is from another service it calls internally.
I've figured out what I was doing wrong. The issue was the "InvocationType". I got it working by changing to...
InvocationType: "RequestResponse"
Then I had to extract the response data like so...
const response_data = JSON.parse(new TextDecoder("utf-8").decode(response.Payload))
I have a problem with correcltly returning the response of a Lambda function that I deploy using the Serverless framework:
module.exports.hello = async (event, context, callback) => {
const content = fs.readFileSync('./cn23_template.html', 'utf-8')
const Vue = require('vue')
const app = new Vue({
template: content,
data: function () {
return event
}
})
const renderer = require('vue-server-renderer').createRenderer()
const html = await renderer.renderToString(app)
const browser = await chromium.puppeteer.launch({
// Required
executablePath: await chromium.executablePath,
// Optional
args: chromium.args,
defaultViewport: chromium.defaultViewport,
headless: chromium.headless || true
});
const page = await browser.newPage();
await page.setContent(html);
let pdf = await page.pdf({ pageRanges: '1', format: 'a4', printBackground: true });
await browser.close();
return {
statusCode: 200,
headers: {
'Content-Type': 'application/pdf',
'Content-Length': pdf.length
},
body: pdf ? pdf.toString('base64') : null,
isBase64Encoded: true
}
}
My serverless.yml file:
functions:
hello:
handler: handler.hello
events:
- http:
path: hello
method: post
integration: lambda
response:
headers:
Content-Type: "'Test'"
Cache-Control: "'max-age=120'"
The problem is that what I return from the function is not correctly mapped to the response. The response doesn't include the statusCode and headers, it just uses the whole returned object as body of the response.
Besides this, the headers as configured in the .yml are also not being used.
It seems like a very silly mistake, but I'm just doing exactly what is inside the Serverless API gateway docs.
So my question is: How do I properly configure the response properties so that the HTTP request gives the correct response using the Serverless framework?
You need to configure your lambda function to be invoked as a lambda-proxy event.
See Serverless Example Lambda Proxy
I have a Controller method: DbController.create to create database entries. This is the following format:
create: function (req, res) {
var params = req.body;
Db.create({
...
There is a route for this Controller method:
'POST /createData': 'DbController.create'
I can use CURL to this URL with no problems (curl -X POST --data 'userId="testuser1"' http://localhost:1337/createData), and from my UI code I can call this using sails-io.js and io.socket.post(....).
The problem is that I want to use this from my Service now (DbService). I'm not sure how I can go about this, because simply using DbController.create requires a req and res parameter to be passed, but all I have is the data/params/body.
Thanks
The best way would be to move the create logic in some service method so that it can be used from anywhere in project. Once this is done, then invoke that method with necessary parameters from DbController.create as well as from some other service.
Sample:
// DBService:
createData: (params, callback) => {
Db.create(params)...
}
// DBController:
create: (req, res) => {
const params = req.body;
DBService.createData(params, (err, results) => {
if (err) {
return res.serverError(err);
}
return res.json(results);
});
}
// SomeOtherService:
someMethod: (params, callback) => {
DBService.createData(params, callback);
}
Another way (which will unnecessary make http request) is to make a HTTP call from service to the API endpoint of DbController.create from the service.
I'm trying to redirect URL to distribute (OAuth 2.0)my slack app with API gateway and lambda function (AWS) but I can't realize how to get the code.
the event that returns is null.
My lambda code :
// Lambda handler
exports.handler = (event, context, callback) => {
var messageTest = {
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
code: event.code
};
var queryTest = qs.stringify(messageTest);
https.get(`https://slack.com/api/oauth.access?${queryTest}`, (res, err) => {
console.log("statusCode: ", res.statusCode);
console.log("headers: ", res.headers);
var data = [];
res.on('data', function(chunk) {
data.push(chunk);
});
res.on('end', function() {
var result = JSON.parse(data.join(''))
console.log(result);
});
});
callback(null);
};
My redirect URL is the lambda URL.
The event that i get is null.
How can i get the "code" from the oAuth 2.0?
Assuming you are using Lambda Proxy integration (and therefore you don't use a Body Mapping Template), the JSON payload that you send to your API Gateway will be received by your Lambda as a stringified JSON in event.body.
So, you'll need to parse that first and you can get your code.
const body = JSON.parse(event.body)
const code = body.code
Reference: Input Format of a Lambda Function for Proxy Integration