How do I handle an express route json error (without "Can't set headers after they are sent.") - express

I've got an Express route which uses response.json to return the response. However, I can't figure out how to catch error cases with it. If I do:
try {
response.json();
} catch (e){
response.send('it went wrong!'
}
or if I do:
.then(() => response.json())
.catch(() => response.send('it went wrong!')
I get a Can't set headers after they are sent error.
That makes sense, since json calls end, and you can't set headers after end is called. However, if I can't edit the response after an error occurs in json, how can I possibly return an error response in such a case?

... Or you could always check:
if (!res.headerSent) {
// do your stuff end with res.json(), res.end(), res.render() or whatever you need
}

Related

How can I fix an Axios interceptor causing property 'status' of undefined error

I have a selection to set permissions for elements to global or private. I'm using the Axios interceptor request to handle looking for the permissions field to have data and, if it does, stringify it. The problem is, it causes me to get a "TypeError: Cannot read property 'status' of undefined" when I attempt to reload the program at all. The only "fix" right now is to log out, remove the interceptor, log in, read it, and then run the check again.
Because of this, I can't even get to the home dashboard of the software. If I clear my cookies, I can go back to the login screen, but no further than that after attempting to log in.
Is there something I'm missing for it? below is the interceptor code. If more information or context is needed, please let me know.
export default {
install: (Vue) => {
Vue.$eventBus = new Vue();
Vue.axios.interceptors.response.use(response => {
return response.data;
}, async error => {
if (error.response.status === 401 && error.config.url != '/api/authentication/login') {
var config = await Vue.$configService.find();
window.location = config.accountPortalUrl;
return
}
console.log(error);
Vue.$eventBus.$emit('notifyUser', 'Uh oh, something went wrong!');
return Promise.reject(error);
});
Vue.axios.interceptors.request.use(
config => {
// check request method -> use post if many params
if (config.data.permissions) {
config.data.permissions = JSON.stringify(config.data.permissions);
}
console.log(config);
return config;
}
);
}
};
Looks like your service API is not responding, this might happen if the user is not authenticated . Your error is at line where you check (error.response.status). Its only possible to get an undefined response when the request was interrupted before response. Most probably if you check your browser network pannel you will see that the preflight check for this request causes a 401 network error. Hence because the preflight failed your actual response comes as undefined. You should sanity check first if your server responded with a response or not and then access the response status.
Something like this might help
if (error.response) {
// Request was made and the server responded successfully
// You can now de-structure the response object to get the status
console.log(error.response.status);
} else if (error.request) {
// request was made but not responded by server
console.log(error.request);
}
So, the answer ultimately was something extremely simple.
if (config.data.permissions)
needed to be
if (config.data && config.data.permissions)

Getting error code 500 no matter what error I send from express using a error handler?

Using a custom error handler, specifically ts-custom-error but even when I roll my own, if I throw the following error after my routes to handle when someone puts in the wrong url/endpoint
app.use((req, res, next) => {
throw HttpError.fromCode(404)
});
app.listen(port, err => {
if (err) {
return console.error(err);
}
return console.log(`server is listening on ${port}`);
});
*edit added additional code
https://github.com/adriengibrat/ts-custom-error/blob/master/src/example/http-error.ts
I get the error message and stack ok, everything works in postman and browser for the body message, but in network on chrome and in the header it still shows a status code of 500. What am I missing?
Can you check your console/terminal for logs? 500 (Internal Server Error) means that there is something wrong with your server. Usually, an unhandled exception.
Are there any other code after this block? If not, your thrown error never gets handled anywhere, causing the 500 error.
You can use this instead:
res.status(404).send({ error: 'Your special error message here!' });

express middleware not sending response

I have a delete route that has 2 middleware functions Authcontroller.protect and authcontroller.restrictTo("admin, "lead-guide")
router
.delete(
authController.protect,
authController.restrictTo("admin", "lead-guide"),
tourController.deleteTour
);
Within restrictTo I have a check to see if the user has the proper "role" to perform that task and if they don't, express is supposed ot send a 403. I'm seeing that express never actually sends the response. it enters the if statement(i see the console successfully printing fialure) and then it just skips sending the response.
exports.restrictTo = (...roles) => {
return (req, res, next) => {
console.log(req.user.role);
if (!roles.includes(req.user.role)) {
console.log("failure");
return res.status(403).json({
status: fail,
message: "you do not have permission to perform this action"
});
console.log(req, res);
}
next();
};
};
Put a try/catch in your inner function and see if there's an exception being thrown.
From looking at your code, if the fail variable (which you don't show a definition for) is not defined, then that would throw an exception and keep the res.json() from executing.

Getting CORS error when using variable in api call

Good day.
When i do the following api call with axios it works just fine but when i try to use a variable in said api call i get a cors error. What am i doing wrong?
When i use it without a variable, this works just fine:
somecall({state}){
axiosB
.get("/lmao/10.0.0.190")
.then(res =>
state.response = res.data);
console.log(state.response)
}
When i use a variable to perform the api call, this gives me a CORS error:
somecall({state, ip}){
axiosB
.get("/lmao/", ip)
.then(res =>
state.response = res.data);
console.log(state.response)
}
The value i am trying to pass is 10.0.0.190 in this case.
Assuming you're using Vuex (are you?), the syntax should be:
somecall({state}, ip){
axiosB
.get("/lmao/" + ip)
.then(res =>
state.response = res.data);
console.log(state.response)
}
Note that the payload comes as a second argument after the deconstructed context, rather than together with it.
Or the problem may be with this line:
.get("/lmao/", ip)
and may need to be changed as above.

How can I mock an http error response in dart?

So I'm doing some unit tests for my http provider.
In one of my tests I want to verify that when I do a POST call and I get an error response with status 409 I do then a call to PATCH and everything works.
This is my code
Future<IdentityResponse> _createUser(dynamic body) {
return http
.post(api, body: json.encode(body))
.catchError((err) {
return _isStatusCode(err, 409) ? _patchUser(body) : throw (err);
});
}
I'm using mockito, and tried first returning a Response like this:
when(http.post(argThat(startsWith(api)), body: anyNamed('body')))
.thenAnswer((_) async => Response("user exists", 409);
And it works... kind of. I catch the error, but then I can't get the status code, I get only the message 'user exists'
If I change to the structure that the backend returns, which is {"error": { "code": 409 }} and I do this:
when(http.post(argThat(startsWith(api)), body: anyNamed('body')))
.thenAnswer((_) async => Response(json.encode(fakeErrorResponse), 409);
Then my catch does not work anymore (??)
I tried then to return an error instead of a response, like this:
when(http.post(argThat(startsWith(api)), body: anyNamed('body')))
.thenAnswer((_) => Future.error(fakeErrorResponse));
Now my catch works again, but the error I get is an _ImmutableMap and I see no easy way to retrieve my data from there.
How can I mock an http error that returns the body that I want and not a simple String?
Thanks