In Rails I'm returning:
render json: { errors: e.response.body.errors }, status: 400
In JavaScript I'm using Axios:
axios.patch('/settings/account', {}, {params: {...
} })
.then((e)=> {
...
console.log('submitted')
})
.catch(function (error, res) {
// only get error that gives 400, but not error msg here, res isn't here
console.log(error);
});
How do I get the e.response.body.errors on my frontend?
Axios reject promises if the server response http status code is anything but 2xx. I see you are sending an error response from the server, but are you sending this response through a http error status? If you arent, the error isnt an error to axios, so the error would show in the "then()" hook, since the promise is resolved.
If you are, then you should see the error whithin error.response.data
Related
I have a custom Axios instance that uses interceptors to return responses. According to the Axios docs, the success interceptor is called whenever there is a 2xx status and the error interceptor is called if it's any status other than 2xx. I want to display an error dialog when the error interceptor is called.
The problem: I want to display the error message coming from the API response in the dialog. For instance, the API may respond with 401 status and still have a custom response with user friendly error messages. However, I am not sure how to obtain the response in the error interceptor function itself.
const responseErrorInterceptor = async (error: AxiosError): ServiceResult<AxiosError> => {
if (error.response) {
store.dispatch(setErrorDialog(undefined, /*display api error response here*/));
//right now it just displays the unfriendly Axios error content
}
return Promise.reject(error);
};
Any ideas if it's possible to achieve this?
Yes, it is possible to achieve this. The AxiosError object passed to the error interceptor function contains a response property which contains the response data from the API. You can use this to get the user friendly error message and display it in the dialog.
For example:
const responseErrorInterceptor = async (error: AxiosError): ServiceResult<AxiosError> => {
if (error.response) {
const userFriendlyErrorMessage = error.response.data.errorMessage;
store.dispatch(setErrorDialog(undefined, userFriendlyErrorMessage));
}
return Promise.reject(error);
};
I am having some problems with catching nodejs fetch exceptions
What I am expecting to happen is:
HTTP error of some sort occurs in my fetch call
CheckResponseStatus function runs and an error an error is thrown with the server error status and text
This error is caught and the ServerError function runs which (just for testing) will just print the error to the console.
However, the error printed to the console is:
Cannot connect to Server. Check you are using the correct IP Address and the server is running.
FetchError: request to http://localhost:3689/api/outputs failed, reason: connect ECONNREFUSED 127.0.0.1:3689
This is implying that the error I have thrown is not being caught, some default fetch error is being caught, and CheckResponseStatus is not being run.
My code is below
Node-Fetch HTTP Request:
async function getStatus(serverip,serverport){
return await fetch(`http://${serverip}:${serverport}/api/outputs`)
.then(this.checkResponseStatus)
.then(res => res.json())
.catch((err) => this.ServerError(err));
}
CheckResponseStatus Function:
checkResponseStatus(res) {
if(res.ok){
return res
}
//will add elseif's here for different HTTP errors
else {
throw new Error(`The HTTP status of the response: ${res.status} (${res.statusText})`);
}
}
ServerError Function:
ServerError(err){
console.log('Cannot connect to Server. Check you are using the correct IP Address and the server is running.');
console.log(err);
}
Thanks for any suggestions or help.
If fetch is unable to connect to the remote server, it will reject. In your code, checkResponseStatus is never called because fetch is never able to get a response; the first two .then blocks are skipped because fetch rejected, so execution goes directly to the .catch block.
If you want network errors to run through checkResponseStatus, you can add a second .catch before the first .then and format the error into a "response":
fetch(`http://${serverip}:${serverport}/api/outputs`)
.catch(err => {
// return a mock failed response for checkResponseStatus to handle
return {
ok: false,
status: -1,
statusText: 'Network Failure',
};
})
.then(this.checkResponseStatus)
.then(res => res.json())
.catch((err) => this.ServerError(err));
However, I believe your code is currently running how I would expect it to - a network failure skips checkResponseStatus, which makes sense because there's no real response to check.
I am making the following request in the front-end with jquery:
try {
await $.post("/test", data, () => {
console.log("received");
})
}
catch (error) {
console.log(error.status);
}
The request is received by a back-end Express router:
app.post("/test", (req, res) => {
console.log("test received")
res.status(400).send("Error message");
})
The back-end sends an error message of the status 400. Although the error is getting caught by the catch statement in the front-end, and the error is being displayed, the browser console still displays the red error of Failed to load resource: the server responded with a status of 400 (Bad Request).
I am wondering if as a best practice, it is ok to have that error message to show up on the browser? I thought about it, and don't see any issue that the error would cause. Furthermore, what would be some of the best practices to handle error return by front-end jQuery/HTTP requests.
I have the following simple GET inside a function.
axios
.get(`/api/search/q=${this.value}`)
.then(res => {
console.log(res.data);
});
The GET 404's if I enter a query (the letter 'a' in this case):
GET http://localhost:7777/api/search/q=a 404 (Not Found)
so, of course I get an Uncaught promise error from the .then:
Uncaught (in promise) Error: Request failed with status code 404
I figured that it must be a simple routing problem, but my express route is:
router.get('/api/search', someController.someFunction)
The function in the controller works (ie responds with the data) as I have used it elsewhere in the app, so I feel that I have narrowed it down to the axios GET not finding the api. But I can't figure out why, as the path looks OK to me.
You were 404 getting because node is expecting only /api/search but your trying /api/search/:q which is different altogether, try
axios.get('/api/search/', {
params: {
q: value
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
since any number of parameters added will not make the URL clumsy, an alternate for
axios.get('/api/search?q=${this.value}').
and on the server
router.get('/api/search', someController.someFunction)
and in your controller
if(req.query.hasOwnProperty('q')){
var q = req.query.q;
}
I have an express route that returns a 400 status and an error message. I want to alert the full error message on the client-side, but the alert only says "Object object" when I alert it. I inspected that object and I don't see the full error message that I see logged to my terminal from the server.
On the server the error message says, "djhbf is not defined" because I typed in some random characters to throw an error message. On the client-side, the object has some properties, but none of them contain the error message "djhbf is not defined". The closest thing to an error message is, "status-text: bad request". How do I retrieve the actual error message "djhbf is not defined" on the client-side?
Here is my server.js code which sends the error message in its catch block of a promise:
app.post('/sendEmails', function(req, res, next) {
axios.get(FEED_URL)
.then(data => {
let jobs = data.data.jobs;
fetchClients(jobs, 'email').then(() => {
res.sendStatus(200);
})
.catch((err) => {
console.log(err);
res.status(400).json(err);
})
})
.catch(error => {
console.log(error);
});
});
Here is the client-side code which alerts the error:
sendEmails() {
axios.post("/sendEmails")
.then(res => {
this.setState({
emailsSent: true,
smsSent: false
});
})
.catch((err) => {
console.log(err);
alert(err);
});
}
Updated
This is not an express issue. axios decorates the error object. You just need to change your client side console.log to this: console.log(err.response.data);
You will also need to update your server side logic since you are using axios on both sides. Try res.status(400).json({msg: 'There was a problem with your request'});
If that works you'll just need to drill down in the err object on the server side to see what you want to send back to the client.
See the Error Handling section of the axios docs.