I am trying to output specific messages on specific responses.
Here is my code:
.post(function(req, res) {
var user = new User(req.body);
user.save(function(err) {
if(err) {
if(err.code == 11000)
res.status(409).json(customHTTPcodeReponses.exists(req.body.email));
};
User.findById(user._id, function(err, createdUser) {
res.status(201).json(customHTTPcodeReponses.created(createdUser));
});
});
});
Flow:
Posting data. I get 201.
Posting same data again. I get 409.
Posting same data again. I get "Could not get any response (POSTMAN)"
Console error:
_http_outgoing.js:335
throw new Error('Can\'t set headers after they are sent.');
[nodemon] app crashed - waiting for file changes before starting...
What could cause this?
Add the User.findById code within an else statement.
user.save(function(err) {
if(err) {
if(err.code == 11000)
res.status(409).json(customHTTPcodeReponses.exists(req.body.email));
}else{
User.findById(user._id, function(err, createdUser) {
res.status(201).json(customHTTPcodeReponses.created(createdUser));
});
}
});
or add a return to the 1st response:
if(err.code == 11000)
return res.status(409).json(customHTTPcodeReponses.exists(req.body.email));
Related
I am using nextjs and mongodb. I performed a GET request but Mongodb returned an empty array. The POST request before that has no problem. Both POST and GET request have status 200 tho.
if (req.method === 'GET') {
try {
const getData = await db.collection(peopleData).find({}).toArray(); // peopleData is from query
res.json(getData);
res.status(200).json({ message: getData });
} catch (error) {
return res.status(500).json({ message: error });
}
}
Thanks in advance
I define axios like below
$axios.onResponse((response) => {
if (response.data.status == 500}
return Promise.reject(response)
}
})
$axios.onError((err) => {
console.log(err)
})
and in fetch i call
async fetch () {
await this.$axios.$get('myapi')
}
but i get error like
RangeError
Maximum call stack size exceeded
I try to reject a success response to error but it not working in ssr. How to fix that thank.
Generally, using try-catch statements are preferred over event handlers (where appropriate).
Try something like this:
async fetch() {
try {
const response = await this.$axios.$get('myapi');
if (response.data.status == 500) {
throw new Error("Some error message");
} else {
// Success action here
}
} catch(err) {
console.log(err);
}
}
Is there any particular reason you're returning a rejected Promise when you get a 500 error? Is there any reason not to throw a generalized error message instead?
I'm having trouble getting redirects to work after accepting a get request from Axios. I do know that the request is being sent and that it at least gets some response from the URL route,
when i console response.data.redirect it return undefined
const onSubmitHandler = (e) => {
e.preventDefault()
axios.get('/get/user')
.then(function (response) {
if (response.data.redirect == '/' || response.data.redirect == '/login' ) {
window.location = "/login"
} else {
console.log(response.data)
}
})
.catch(function(error) {
window.location = "/login"
})
}
I received status code 302 but it automatically redirects to the page without page refresh shows the redirected page on the same page in a div section.
Anyone knows how can I use interceptor with Axios such that if the status code fall in 200 series then does something else page refresh. I checked the Axios docs but there is no implementation
Try this for interceptors
axios.interceptors.response.use(
response => {
return response.data;
},
err => {
//return new Promise((resolve, reject) => {
//err.response.status for getting error status
// }
throw err;
});
}
);
With axios the code is:
export const createBlaBla = (payload) => {
return axios.post('/some-url', payload)
.then(response => response)
.catch(err => err);
}
And then I'm using this with redux-saga like this:
function* createBlaBlaFlow(action) {
try {
const response = yield call(createBlaBla, action.payload);
if (response) {
yield put({
type: CREATE_BLA_BLA_SUCCESS
});
}
} catch (err) {
// I need the error data here ..
yield put({
type: CREATE_BLA_BLA_FAILURE,
payload: 'failed to create bla-bla'
});
}
}
In case of some error on the backend - like invalid data send to the backend - it returns a 400 response with some data:
{
"code":"ERR-1000",
"message":"Validation failed because ..."
"method":"POST",
"errorDetails":"..."
}
But I don't receive this useful data in the catch statement inside the saga. I can console.log() the data in the axios catch statement, also I can get it inside the try statement in the saga, but it never arrives in the catch.
Probably I need to do something else? ... Or the server shouldn't return 400 response in this case?
So, I came up with two solutions of this problem.
===
First one - very dump workaround, but actually it can be handy in some specific cases.
In the saga, right before we call the function with the axios call inside, we have a variable for the errors and a callback that sets that variable:
let errorResponseData = {};
const errorCallback = (usefulErrorData) => {
errorResponseData = usefulErrorData;
};
Then - in the axios method we have this:
export const createBlaBla = (payload, errCallback) => {
return axios.post('/some-url', payload)
.then(response => response)
.catch(err => {
if (err && err.response.data && typeof errCallback === 'function') {
errCallback(err.response.data);
}
return err;
});
}
This way, when we make request and the backend returns errors - we'll call the callback and will provide the errors from the backend there. This way - in the saga - we have the errors in a variable and can use it as we want.
===
However, another solution came to me from another forum.
The problem I have is because in the method with the axios call I have catch, which means that the errors won't bubble in the generator. So - if we modify the method with the axios call like this:
export const createBlaBla = (payload) => {
return axios.post('/some-url', payload)
}
Then in the catch statement in the saga we'll have the actual backend error.
Hope this helps someone else :)
In your API call you can do the following:
const someAPICall = (action) => {
return axios.put(`some/path/to/api`, data, {
withCredentials: true,
validateStatus: (status) => {
return (status == 200 || status === 403);
}
});
};
Please note the validateStatus() part - this way when axios will encounter 200 or 403 response, it will not throw Error and you will be able to process the response after
const response = yield call(someAPICall, action);
if (response.status === 200) {
// Proceed further
} else if (response.status === 403) {
// Inform user about error
} else {
...
}
I'm building facebook chatbot using AWS Lambda and MongoDB. At the moment, my application is pretty simple but I'm trying to nail down the basics before I move onto the complex stuff.
I understand AWS Lambda is stateless but I've read adding below line in handler along with variables initialized outside handler, I don't have to establish DB connection on every request.
context.callbackWaitsForEmptyEventLoop = false;
(I've read this from this article; https://www.mongodb.com/blog/post/optimizing-aws-lambda-performance-with-mongodb-atlas-and-nodejs)
I'm adding my entire code below
'use strict'
const
axios = require('axios'),
mongo = require('mongodb'),
MongoClient = mongo.MongoClient,
assert = require('assert');
var VERIFY_TOKEN = process.env.VERIFY_TOKEN;
var PAGE_ACCESS_TOKEN = process.env.PAGE_ACCESS_TOKEN;
var MONGO_DB_URI = process.env.MONGO_DB_URI;
let cachedDb = null;
let test = null;
exports.handler = (event, context, callback) => {
var method = event.context["http-method"];
context.callbackWaitsForEmptyEventLoop = false;
console.log("test :: " + test);
if (!test) {
test = "1";
}
// process GET request --> verify facebook webhook
if (method === "GET") {
var queryParams = event.params.querystring;
var rVerifyToken = queryParams['hub.verify_token']
if (rVerifyToken === VERIFY_TOKEN) {
var challenge = queryParams['hub.challenge'];
callback(null, parseInt(challenge))
} else {
var response = {
'body': 'Error, wrong validation token',
'statusCode': 403
};
callback(null, response);
}
// process POST request --> handle message
} else if (method === "POST") {
let body = event['body-json'];
body.entry.map((entry) => {
entry.messaging.map((event) => {
if (event.message) {
if (!event.message.is_echo && event.message.text) {
console.log("BODY\n" + JSON.stringify(body));
console.log("<<MESSAGE EVENT>>");
// retrieve message
let response = {
"text": "This is from webhook response for \'" + event.message.text + "\'"
}
// facebook call
callSendAPI(event.sender.id, response);
// store in DB
console.time("dbsave");
storeInMongoDB(event, callback);
}
} else if (event.postback) {
console.log("<<POSTBACK EVENT>>");
} else {
console.log("UNHANDLED EVENT; " + JSON.stringify(event));
}
})
})
}
}
function callSendAPI(senderPsid, response) {
console.log("call to FB");
let payload = {
recipient: {
id: senderPsid
},
message: response
};
let url = `https://graph.facebook.com/v2.6/me/messages?access_token=${PAGE_ACCESS_TOKEN}`;
axios.post(url, payload)
.then((response) => {
console.log("response ::: " + response);
}).catch(function(error) {
console.log(error);
});
}
function storeInMongoDB(messageEnvelope, callback) {
console.log("cachedDB :: " + cachedDb);
if (cachedDb && cachedDb.serverConfig.isConnected()) {
sendToAtlas(cachedDb.db("test"), messageEnvelope, callback);
} else {
console.log(`=> connecting to database ${MONGO_DB_URI}`);
MongoClient.connect(MONGO_DB_URI, function(err, db) {
assert.equal(null, err);
cachedDb = db;
sendToAtlas(db.db("test"), messageEnvelope, callback);
});
}
}
function sendToAtlas(db, message, callback) {
console.log("send to Mongo");
db.collection("chat_records").insertOne({
facebook: {
messageEnvelope: message
}
}, function(err, result) {
if (err != null) {
console.error("an error occurred in sendToAtlas", err);
callback(null, JSON.stringify(err));
} else {
console.timeEnd("dbsave");
var message = `Inserted a message into Atlas with id: ${result.insertedId}`;
console.log(message);
callback(null, message);
}
});
}
I did everything as instructed and referenced a few more similar cases but somehow on every request, "cachedDb" value is not saved from previous request and the app is establishing the connection all over again.
Then I also read that there is no guarantee the Lambda function is using the same container on multiple requests so I made another global variable "test". "test" variable value is logged "1" from the second request which means it's using the same container but again, "cachedDb" value is not saved.
What am I missing here?
Thanks in advance!
In short AWS Lambda function is not a permanently running service of any kind.
So, far I know AWS Lambda works on idea - "one container processes one request at a time".
It means when request comes and there is available running container for the Lambda function AWS uses it, else it starts new container.
If second request comes when first container executes Lambda function for first request AWS starts new container.
and so on...
Then there is no guarantee in what container (already running or new one) Lambda function will be executed, so... new container opens new DB connection.
Of course, there is an inactivity period and no running containers will be there after that. All will start over again by next request.