How to Handle Custom Lambda Errors in API Gateway Using Python - python-3.x

In my app i want handle the custom errors like 500,403,201,400 errors, i have tried in nodejs its working fine but i am working with python so i did'nt find any solution in python to handle the http status codes, so is there any way to handle them that helps me a lot.
var myErrorObj = {
status : 500,
errorType : "InternalServerError",
httpStatus : 233,
requestId : context.awsRequestId,
trace : {
"function": "abc()",
"line": 123,
"file": "abc.js"
}
};
const responseInvoke = (eventData) => {
return lambda.invoke({
FunctionName: 'test777',
Payload: JSON.stringify({"eventData":event}) // pass param
}).promise();
};
responseInvoke(event)
.then(res => {
console.log('*** response *** ', res);
const parsedRes = JSON.parse(res.Payload);
if(parsedRes.status === 'success') {
callback(null, res.Payload);
} else {
context.fail(JSON.stringify(myErrorObj));
}
})
.catch(err => {
console.log(err);
context.fail(JSON.stringify(myErrorObj));
});
here is the code which i have invoked from python lambda to nodejs lambda in python lambda i am returning success (or) fail messages to nodejs lambda based on the message i am sending the response to API gateway.

Related

Google Cloud Function failed with timeout

I have a Pub/Sub triggered cloud function that calls an API end-point and logs the message. But I am not seeing all log messages being logged in console except everything right before calling API.
Once the API is called I am logging the response, and exception messages in case of any error.
It is logging: Function execution took 120015 ms. Finished with status: timeout Earlier the default timeout was set to 60 sec, later I increased it to 120 sec. Still the problem persist.
I am not understanding the issue here since it is working locally without any issues.
Here I have custom module to log messages to Winston and GCP console (it doesn't have any issue and working fine).
Code calling the API module:
const console = require('./logging-utils');
const portal_api = require('./api-utils');
exports.triggerPortalNotifier = async (event, context) => {
try {
/*
.....
*/
console.metadata.cloudFunction = cf_name;
console.metadata.requestId = requestId;
console.metadata.organizationId = organizationId;
console.metadata.instanceId = instanceId;
console.logMessage(`Event received with payload: some message`);
var payload = {
//payload to API
}
var response = await portal_api.notifyPortal(payload);
console.logMessage(`Response received from portal API is: ${JSON.stringify(response.data)}`);
}
else {
throw new Error(`Invalid message received: ${_message}`);
}
}
catch (error) {
console.logMessage(`Portal API failed with exception: ${error}`);
throw new Error(`${error.message}`);
}
}
Code that make API request (using axios module)
require('dotenv').config();
const axios = require('./axios-instance');
const console = require('./logging-utils');
const nextgen_api = {
notifyPortal: async (payload) => {
try {
const config = {
headers: {
'Authorization': process.env.PORTAL_AUTHORIZATION_TOKEN,
'Content-Type': "application/json",
'Accept': "application/plain"
}
}
console.logMessage(`Input paylod for API end-point: ${process.env.PORTAL_API} => ${JSON.stringify(payload)}`)
const response = await axios.post(process.env.PORTAL_API, JSON.parse(JSON.stringify(payload)), config);
console.logMessage(`Response from API: ${JSON.stringify(response.data)}`);
return response;
}
catch (err) {
if (err.response && err.response.status !== 200) {
console.logMessage(`API call failed with status code: ${err.response.status} `);
throw new Error(`API call failed with status code: ${err.response.status} `);
}
else {
console.logMessage(`API call failed with ${err.stack}`);
throw new Error(`API call failed with status code: ${err.stack} `);
}
}
}
}
module.exports = my_api;
Message Response from API: ${JSON.stringify(response.data)} is not being logged.
Any help here is appreciated.

Axios returns 401 Error writing to Firebase

I currently have a scheduled function running as a cloud function that uses Axios to write to the Realtime Database in Firebase. However, I continue to receive the error:
'Request failed with status code 401'
Which seems to be an authorization error. I am using Axios with authorization using a legacy token, specifically the secret for the database.
Am I using authorization wrong here or is there another way to do this? The issue I have is using authorization for access specifically in a scheduled function.
App.js
exports.callTo = functions.pubsub.schedule("* * * * *").onRun((context) => {
let searchTrends;
googleTrends.dailyTrends({
trendDate: new Date("2021-10-20"),
geo: "US",
}, function(err, res) {
if (err) {
functions.logger.error(err);
} else {
searchTrends = JSON.parse(res).default.trendingSearchesDays
.trendingSearches;
const query = searchTrends[2] + " since:2021-10-20";
return axios.put("https://testtter-c0e48-default-rtdb.firebaseio.com/searchTrends.json?auth=<account_secret>", {trends: searchTrends})
.then((res) => {
functions.logger.log("Result: " + res);
})
.catch((error) => {
functions.logger.log("Error: " + error);
});
}
});
});

How can I capture HttpErrorResponse status and display it in angular component

I have an angular project back end with node.js, how can I call and get httpErrorResponse status or headers to display in my components page when my server is down or not responding.
here is my component function code:
UpdateData(){
this.newServices.updateNews(result, result.id).subscribe(
(res)=>{
console.log(res)
}),
(error)=>{
console.log(error)
}
}
my service.ts function:
updateNews(data, id) {
try {
return this.http.post(this.baseurl + "/news/update/" + id, data)
} catch (err) {
this.handleError(err);
}
}
how can I check in my component the http responses so that I can display messages on the browser
Generally its not advisable to show the error message to the user that returned from server. For example the error may be: Cant reach the xx.xx.xx due to CORS policy. So if u show this the user cant understand whats happening. So its advisable to use a toaster Service to show error to user.
https://www.npmjs.com/package/ngx-toastr
getPlayersList() {
this.playerService.getPlayersList().subscribe((res: any) => {
this.playersData = res.data;
}, err => {
this.toasterService.showFailure('Sorry something went wrong');
})
}
In some scenarios if u want to show the error thats coming from api like 500 response u can do in this way
getPlayersList() {
this.playerService.getPlayersList().subscribe((res: any) => {
this.playersData = res.data;
}, err => {
this.toasterService.showFailure(err.err.message);
})
}
Try this:
In your service:
updateNews(data, id) {
return this.http.post(this.baseurl + "/news/update/" + id, data)
}
In your function:
this.newServices.updateNews(result, result.id).subscribe(
(res)=>{
console.log(res)
}),
(error)=>{
console.log(error)
}

Postman call to AWS API Gateway to trigger AWS lambda function not working

I have created an api, when called, triggers the lambda function, written in nodejs, to take the json(array of objects) and insert the data into dynamodb. For each object in the array, the function creates a PutRequest object and when finished calls the batchWriteItem function. When I test in the aws console everything works fine but when I try in postman I get a 500 error. I know that the event is different when coming from postman vs the console and you are supposed to reference "event.body" if you want to access the json however when I do that I get an error with event.body.ForEach: "Cannot read property 'forEach' of undefined" in the console and a 500 error in postman. Below is the code that works in the console
var dynamo = new AWS.DynamoDB({region: 'us-east-1',});
exports.handler = (event, context, callback) => {
const done = (err, res) => callback(null, {
statusCode: err ? '400' : '200',
body: err ? err.message : res,
});
var params = {
RequestItems: {
"Lead": []
}
}
event.forEach(x => {
params.RequestItems.Lead.push({
PutRequest: {
Item: {
"Address": {S: x.Address},
"City": {S: x.City},
"State": {S: x.State},
"Zipcode": {S: x.Zipcode},
"Owner_First_Name": {S: x.Owner_First_Name},
"Owner_Last_Name": {S: x.Owner_Last_Name}
}
}
})
})
dynamo.batchWriteItem(params, done);
};
When the lambda receive the json body from api gateway, it will be passed as a json string.
To convert the json string to json, You need to parse the event.body.
const body = JSON.parse(event.body)
Then you can do body.forEach
Hope this helps

How to handle a promise with a callback with nodejs?

I'm making an app using the nano npm module with nodejs, one of my async functions is intended to create an object in Cloudant but I'm not pretty sure how to handle a Promise.resolve with a callback which is an important part of the response which is supposed my server has to respond.
I do well with creating the document but the next part is to check if there was an error trying to do it, so if there is an error I'd like my server to return an object with the classic error message.
This is my code:
exports.createMeeting = async (body) => {
var response;
object = {"name": "Billy Batson"}
console.log("-------------")
//Trying to insert the document
response = await Promise.resolve(db.insert(object).then((body, err) => {
//This is the part I'm trying to check if the db.insert did fail
if (err) {
response = {
message: 'Failure',
statusCode: '500',
}
console.log(JSON.stringify(response));
} else {
response = {
message: 'Ok',
statusCode: '201',
}
console.log(JSON.stringify(response));
}
}));
}
console.log("******* ", JSON.stringify(response));
return response;
}
If I try to run this code the output is:
-------------
{"message":"Ok","statusCode":"201"}
******* undefined
The first printed object is because the code reached the part where I assign the response object with the status code 201 but the second part doesn't recognize the value of 'response' and the line "return response;" actually doesn't return it, I've confirmed it with postman (it doesn't get a response).
I think the problem here is that I'm not handling correctly the .then() syntax, I've tried changing to a classic callback with:
response = await Promise.resolve(db.insert(object),(body, err) => {
if (err) {
response = {
message: 'Failure',
statusCode: '500',
}
console.log(JSON.stringify(response));
} else {
response = {
message: 'Ok',
statusCode: '201',
}
console.log(JSON.stringify(response));
}
});
But it prints:
-------------
******* {"ok":true,"id":"502c0f01445f93673b06fbca6e984efe","rev":"1-a66ea199e7f947ef40aae2e724bebbb1"}
Which means the code is not getting into the callback (it's not printing 'failure' or 'ok' objects)
What I'm missing here?:(
nano provides promise-based API when a callback is omitted.
This is not how errors are handled in promises. then callback has 1 parameter, there
will be no err.
It's expected that a promise is rejected in case there's an error. Promise.resolve is redundant when there's already a promise and is always redundant with async..await.
It should be:
try {
const body = await db.insert(object);
response = {
message: 'Ok',
statusCode: '201',
}
} catch (err) {
response = {
message: 'Failure',
statusCode: '500',
}
}

Resources