Nextjs ERR_HTTP_HEADERS_SENT in POST handler, from a GET request - next.js

So I am making a simple route for my app, which basically, calls another server and returns the data back to me (since CORS is not enabled, I cant do it from the frontend atm).
const getBotState: NextApiHandler = async (req, res) => {
console.log(req.method);
switch (req.method) {
case 'GET':
try {
res.status(200).json({ someData: "hi get" });
} catch (e) {
console.log(e);
res.status(404).json({ err: e });
}
case 'POST':
try {
res.status(200).json({ someData: "hi post" }); // this is the line that breaks it
} catch (e) {
console.log('post error');
console.log(e);
res.status(404).json({ err: e });
}
default:
}
};
export default getBotState;
The problems started after I added the POST case.
If I comment out the res.status.... line, the error will go away, but I am making ONLY GET requests currently to this API endpoint, I am not making POST requests at all, and yet, the catch block in the POST case is what triggers the error.

switch has a unique attribute and its attribute is its ability to 'fall-through' and access the next case statement. This is by design, every programming language does this.
How to fix this? Add a break.
const getBotState: NextApiHandler = async (req, res) => {
console.log(req.method);
switch (req.method) {
case 'GET':
try {
res.status(200).json({ someData: "hi get" });
} catch (e) {
console.log(e);
res.status(404).json({ err: e });
}
break;
case 'POST':
try {
res.status(200).json({ someData: "hi post" }); // this is the line that breaks it
} catch (e) {
console.log('post error');
console.log(e);
res.status(404).json({ err: e });
}
break;
default:
}
};
export default getBotState;
And then you're done!
From MDN Docs:
The optional break statement associated with each case label ensures that the program breaks out of switch once the matched statement is executed and continues execution at the statement following switch. If break is omitted, the program continues execution at the next statement in the switch statement. The break statement is not required if a return statement precedes it.

Related

Sequelize delete request with payload works with Postman but not with Vue Frontend implementation

I am trying to send PUT and DELETE requests with my express backend to a sqlite database. Put request works fine but DELETE request always fails.
I already checked the headers within the network tab, it seems to be the right one for both (application/json)
With postman, I can easily delete entries, but with my frontend the body does not seem to be set correctly.
const countryToPush = {title: countryName}
try{
await CountryService.post(countryToPush)
console.log(countryName + ' added!')
} catch(err)
{
console.log(err)
}
},
removeFromDb: async function(countryName){
const countryToDelete = {title: countryName}
try{
await CountryService.delete(countryToDelete)
console.log(countryName + ' deleted!')
} catch(err)
{
console.log(err)
}
}
This is within my vue file where I get the 'countryName' from an on click function.
try {
const country = await Country.create(req.body)
res.send(country)
} catch (err) {
res.status(500).send({
error: 'an error has occurred trying to create the country'
})
}
},
async delete (req, res) {
try {
const toDelete = await Country.findOne({
where: {
title: req.body.title
}
})
await toDelete.destroy()
res.send(req.body.title + ' was deleted')
} catch (err) {
res.status(500).send({
error: 'an error has occurred trying to delete the country'
})
}
}
Whereas this is the example from my sqlite calls
Unfortunately, the DELETE request from my vue frontend always fails and gives me the defined error 500 an error has occurred trying to delete the country.
Any ideas what else I could try to get it working?
Model.delete() is not a Sequelize function, you want to use Model.destroy().
await CountryService.destroy(countryToDelete)
Right now you are swallowing the actual error - add console.log(err) to your catch to see that it is probably saying CountryService.destroy is undefined.

Meteor Method w/ Mongo Aggregation returning Undefined on Client but not on Server

So I've just started with Meteor and really JavaScript so forgive the messy coding as I am new to all of this please. I'm using a Mongo Aggregation to do some server side math and the method is returning undefined on the client but the server-side console log is returning the correct information. Here is the server method...
Meteor.methods({
'schoolHealth': function() {
var pipeline = [
{
"$group": {
"_id": null,
"total": { "$avg": "$roomHealth"}
}
}
];
Equipment.aggregate(pipeline, function(err, result) {
if (err) {
throw err;
console.log("Error in finding school health average:" + result);
} else {
console.log(result[0].total)
return result[0].total;
}
});
}
});
And on the client...
Meteor.call('schoolHealth', function(error, result) {
if (error) {
console.log(error);
} else {
console.log(result);
Session.set('health', result);
}
});
I'm calling the Session on a blaze template but the method is failing before that happens. Also, I have tried not using a Session and the result is the same. I have read into Sync vs. Async but I don't know enough about it to know if I am doing something wrong there. Thanks ahead of time for the help.

How to display ionic2 Alert after Firebase changeEmail

I have the following function to change the email on a Firebase user account. I want to display an ionic2 alert when complete, whether it was successful or there was an error. From my code below I do get the alert to display BUT it is blank. Most likely it is a timing issue on the Firebase promise but I don't know how to fix it.
private doChangeEmail(data): void {
var myAlert: {
title?: string,
subtitle?: string
} = {};
this.auth.ref.changeEmail({
oldEmail: data.oldemail,
newEmail: data.newemail,
password: data.password
}, function(error) {
if (error) {
switch (error.code) {
case "INVALID_PASSWORD":
myAlert.title = 'Invalid Password';
myAlert.subtitle = 'The specified user account password is incorrect.';
break;
case "INVALID_USER":
myAlert.title = 'Invalid User';
myAlert.subtitle = 'The specified user account does not exist.';
break;
default:
myAlert.title = 'Error creating user';
myAlert.subtitle = error;
}
} else {
myAlert.title = 'DONE';
myAlert.subtitle = 'User email changed successfully!';
}
});
let alert = Alert.create({
title: myAlert.title,
subTitle: myAlert.subtitle,
buttons: [{
text: 'OK',
handler: () => {
}
}]
});
this.nav.present(alert);
}
put the alert code inside the promise result....
this.auth.ref.changeEmail({
oldEmail: data.oldemail,
newEmail: data.newemail,
password: data.password
}, function(error) {
if (error){
// do error stuff..
} else {
// do success stuff..
}
// show alert here...
})
I found the following comment by Frank van Puffelen which solved my issue:
You're using this inside a callback function, where it has a different meaning. One solution is to use fat-arrow/rocket notation for the callback, which ensures this is what you expect it to be:
The correct syntax should be
this.auth.ref.changeEmail({
oldEmail: data.oldemail,
newEmail: data.newemail,
password: data.password
}, (error) => {
if (error){
// do error stuff..
} else {
// do success stuff..
}
// show alert here...
})
and the alert shows correclty as pointed out by Aaron Saunders

cannot catch Meteor.Error in client when error in server inside Meteor.bindEnvironment

I am not able to get the error in client's Meteor.call error callback when in the server code, an error occurs inside Meteor.bindEnvironment. Below is example code to replicate
In the server
Meteor.methods({
customMethod: function(arg1, arg2){
Stripe.customers.create({
email: "email#here.com,
description: "blah blah",
source: token,
metadata: {
planId: planId,
quantity: n
},
plan: planId,
quantity: n
}, Meteor.bindEnvironment(function (err, customer) {
if(err){
console.log("error", err);
// TODO cannot catch this error on the client
throw new Meteor.Error(err.rawType, err.message)
}
}))
}
})
In the client inside a Meteor event,
Meteor.call('customMethod', arg1, arg2, function (err, resp) {
if(err){
Session.set('some-error', err)
}
if(resp){
// TODO cannot catch errors throwing from the server
// when inside Meteor.bindEnvironment
Session.set('some-success', true)
}
});
The session variables are never set. Any help would be great. Thanks!
The second argument to Meteor.bindEnvironment is an error-handler that gets called whenever an exception is thrown within the callback you supplied as the first argument. So you can do something like this to get the error passed back to the client:
Meteor.bindEnvironment(function (err, customer) {
if (err) throw err
...
}, function (err) {
if (err) throw new Meteor.Error(err.message)
})
UPDATE
Apologies, that was a bit hasty. The problem is the fact that your error (and potentially results) are coming from an asynchronous callback, so your method function will have finished executing, and implicitly returned undefined (which gets passed to the client as null) by the time the callback does anything.
Historically, you'd resolve this with a future, but now we have promises, which are better:
Meteor.methods({
customMethod (arg1, arg2) {
return new Promise((resolve, reject) => {
Stripe.customers.create({
email: "email#here.com,
...
}, Meteor.bindEnvironment(function (err, customer) {
if(err){
reject(err)
}
resolve(customer)
})).catch(e => { throw new Meteor.Error(e) })
}
})
Meteor methods are clever enough to wait for promises to resolve or reject and return the result (or error) via DDP. You still need to catch the error and formally throw it, but your method call will wait for you to do so.

Can't catch meteor error thrown in Method from Event

I have a method and it throws an error so I can catch it in my event and display it to the user, like this:
Meteor.methods({
addPlayer: function(nickname) {
if (nickname == "") {
throw new Meteor.Error('empty-nickname', 'You must choose a nickname');
} else {
Player.insert({
nickname: nickname,
});
}
},
})
and in my event
'submit form': function (e) {
e.preventDefault();
var nickname = $('input').val();
Meteor.call('addPlayer', nickname, function(error, result) {
if (error) {
console.log(typeof error);
console.log(error);
}
});
}
However, meteor still throws an Exception while simulating the effect of invoking 'addPlayer', and the error variable is not an error object, but a string with the same message as the console log, so I get two errors in my console instead of an error object.
Wrapping method.call in a try/catch does not work.
What am I missing here?
-- Edit
Here is an print screen of the result:
Image link for full resolution: http://i.stack.imgur.com/zABar.png
Throw the error only on the server. Wrap it inside if(!this.isSimulation) {}
Meteor.methods({
addPlayer: function(nickname) {
if (nickname == "") {
if(!this.isSimulation) {
throw new Meteor.Error('empty-nickname', 'You must choose a nickname');
}
} else {
Player.insert({
nickname: nickname,
});
}
},
})

Resources