Axios does not send appropriate error response [React] - javascript

I'm trying to handle the error responses from Axios with React, but when i try to console log it the error is Network error and the error.response is undefined.
The request is a simple POST with the Authorization header correctly setted, when I try to do the same request on Postman it works correctly and I'am able to see the error response.
The request is made after the user fills a form and click on a button.
async function create() {
const response = await Axios.post(
"/api/disposal-requests/", // the base url is setted when the application mounts `Axios.defaults.baseURL = process.env.REACT_APP_API_URL`
{
description: "Description",
url: "Url",
key: "Key",
location_geoname_id: "City",
}
);
return response.data;
}
When a user clicks on a button there is another function that calls the create.
async function onClick() {
try {
await create();
// Everything works fine when there are no errors
} catch(error) {
// Here error.response is undefined
}
}
This is what i receive in the console.log, in the Network tab I can see the error status is 400 but even there there is no error response, I'am able to see the error response only on Postman.
Does anyone know what's wrong here ?

Please write await before creat(). so that if any any error occurs, catch with get that
async function onClick() {
try {
await create();
// Everything works fine when there are no errors
} catch (error) {
// Here the error response is undefined
}
}

Related

Jest test that simulates throwing an Axios exception fails with empty error message

I am trying to write a Jest test to cover a scenario whereby an axios.post (in the code I am trying to test) throws and handles an exception. The test successfully throws an error for a mocked axios instance and the appropriate catch block in the code I am wishing to test is reached. However, the error/exception message is empty. This then causes some assertions that I am trying to do in the test to fail.
The relevant section of the code to test looks as follows:
try {
// Call the token endpoint with the client/user credentials and check the response.
const { status, data } = axios.post(authenticationConfig.tokenEndpoint,
'grant_type=client_credentials', { headers });
if (status === StatusCodes.OK) {
...
}
}
catch(err) {
console.log(JSON.stringify(err));
res.status(StatusCodes.UNAUTHORIZED);
res.json(err.response.data.error);
}
The corresponding test looks like:
it('cannot get access token', async () => {
const response = {
response: {
data: {
error: 'My error'
}
}
};
const req = {
headers: {
'authorization': 'Basic client_id:client_secret'
}
};
mockedAxios.mockImplementation(() => {
throw new Error(response);
});
const provide = await authenticationMiddleware.provide(req, res, next);
await provide(req, res, next);
expect(mockedAxios).toBeCalledTimes(1);
expect(res.status).toHaveBeenCalledTimes(1);
expect(res.status).toHaveBeenCalledWith(StatusCodes.UNAUTHORIZED);
});
The err object in the catch block is logged out as an empty object even though from the test I'm throwing an error with a fully populated object. The test passes if I remove the 'res.json' statement from the catch block.
● authentication middleware › cannot get access token
TypeError: Cannot read property 'data' of undefined
89 | console.log(JSON.stringify(err));
90 | res.status(StatusCodes.UNAUTHORIZED);
> 91 | res.json(err.response.data.error);
Any ideas most welcome please. No doubt the way that I'm mocking Axios and causing it to throw an exception is wrong. The code does enter the catch block but the 'err' object is empty for some reason.
Many thanks.

nodejs app crash on openai dall-e 2 api rejected request

I'm surely dumb, but I'm not able to figure out how to handle openai api rejected requests
( for the context, dall-e 2 is an image generator )
when user tries to generate forbidden images, my nodejs app just exits
async function start(arg) {
try{
// generate image
const response = openai.createImage({
prompt: arg,
n: 1,
size: "1024x1024",
});
// on success response
response.then(res =>{
console.log("ok");
})
response.catch(err =>{
console.log(err);
});
} catch(e){
console.log(e);
}
}
it gives me something like that on the exit :
data: {
error: {
code: null,
message: 'Your request was rejected as a result of our safety system. Your prompt may contain text that is not allowed by our safety system.',
param: null,
type: 'invalid_request_error'
}
}
tried using response.catch and try catch without success, the app just exits everytime
I at least want to ignore this error in the first place
in a second hand, I would like to console.log the given message (data.error.message)
I don't know what to do to by honest, don't even understand why try catch isn't working
With the details given, my guess would be that the Promise returned by getImages is being rejected. You could debug this a bit by adding some additional logs into your .catch callback and catch statement.
How to do this really depends on what you're trying to do with this api, the code as it's currently written would log something and exit no matter what happens.
There's a couple ways to handle this
Use your .catch to handle the error. Utilizing promise chainability you can get something like this
openai.createImage({
prompt: arg,
n: 1,
size: "1024x1024",
user: msg.author.id,
})
.catch((e) => {
if (e.data.error.message.includes('safety system')) {
return 'something'
}
console.error(e)
})
If you need the response object, the asnwer might be different. Looks like the openai package is built on axios and you can pass axios options into it. See https://axios-http.com/docs/handling_errors and the Request Options section of https://npmjs.com/package/openai
EDIT
I found my solution thanks to #JacksonChristoffersen
Basically I was getting http status 400
I just added request options from axios to validate http status smaller than 500
Here's the solution:
async function start(arg) {
try{
// generate image
const response = openai.createImage({
prompt: arg,
n: 1,
size: "1024x1024",
},{
validateStatus: function (status) {
return status < 500; // Resolve only if the status code is less than 500
}
});
// on success response
response.then(res =>{
console.log("ok");
})
response.catch(err =>{
console.log(err);
});
} catch(e){
console.log(e);
}
}

Why Request API when error always goes to catch

I have some questions about requesting API from the server. I make a function for request API, the example I have a request API login when the user fills the email wrong, response API is "email or password is wrong!", when I try in postman is success the response but when I try in my code the response always from the catch, not from response API. My code for request API like below
const handleSubmitLogin = async (input) => {
try {
const result = await axios.post(`${BASE_URL}/users/client/login`, input);
if (result.status == 200 || result.status === "success" || result.status == 201) {
await setAuthKey(result.data.data.token);
await setLoggedUser(JSON.stringify(result.data.data));
dispatch(setUserLogin());
dispatch(setDataLogin(result.data.data));
} else {
setModalActive({ status: true, data: result.message });
}
} catch (error) {
console.log(error);
setModalActive({ status: true, data: translations["please.try.again"] });
}
};
when a user fills an email or password wrong, the response is always from the catch response not from the API response. Can anyone give suggestions for this case?
Edit:
This is result from when user wrong password
If your API responds with a non-successful status code (>= 400), Axios will reject the promise and your code will go into the catch block.
You can still access the response data via error.response.data. See Axios - Handling Errors
try {
const result = await axios.post(`${BASE_URL}/users/client/login`, input);
// etc...
} catch (err) {
console.warn("login", error.toJSON());
setModalActive({
status: true,
data: error.response?.data?.message ?? translations["please.try.again"],
});
}
It's important to use optional chaining since the error may not have a response or data depending on what exactly failed.

Axios post entering catch block even after successful Rest API call completion

My axios post request is not returning the value returned by the API in a non success 401 scenario. It works fine when its a success scenario.
My reset Password API returns the status code, and a message for every call. when I use post man to test its output for resetting a password, giving incorrect current password, I get
Postman Output:
statusCode: 401,
headers: {
.......
........
},
body: "{"code":"NotAuthorizedException","name":"NotAuthorizedException","message":"Incorrect username or password."}" <--- This is the body output
But in my axios post, it goes to the catch block:
await Axios.post(resetAPIUrl, resetParams, config).then(value=> {
console.log(`Returned data ----> ${JSON.stringify(value)}`);
resolve(value);
}).catch(error=>{
console.log(`Failing--->${error}`)
reject(error)
});
this is the error that I am getting in the catch block of Axios post:
Error: Request failed with status code 401
The error reason is correct. But why isn it going into catch block? Its a successful completion of the process. Calling the API directly from post man gives me the correct output structure.
Interceptor was the answer. Since Axios doesn't consider any response other than 200 as the success scenario, interceptors can be used to capture the other responses:
{
Axios.interceptors.request.use(req=>{
console.log(`This is the request ---> ${req.method} ${req.url}`)
return req;
})
Axios.interceptors.response.use(res => {
console.log(`res status ---> ${res.status}`)
resolve(res)
return res;
}, (error)=>{
console.log(`This is the error status ---> ${error.response.status}`)
if(error.response.status === 401){
resolve(error.response);
}
})
await Axios.post(resetAPIUrl, resetParams, config);

Set timeout inside an async function with try and catch does not catch error

I have an Ionic 3 App where I use async and await of ES6 features for syntactic sugar of promises. I know this is just a little bit basic question or because I am just new in using async and await feature.
Now the problem is I had a setTimeout inside my async function of signIn method to authenticate the user.
This is my code below:
async signIn() {
try {
this.loader = true // Present a loader
this.backgroundLoader = this.loadingCtrl.create({ content: 'Signing you in...' });
this.backgroundLoader.present();
// Response from server
const response: any = await this.authService.loginDriver(this.loginForm.value)
console.log(response)
if (response.status == 200) { // If success response
const token = await this.storage.set('token', response.data.token)
console.log('token:', token)
this.events.publish('driver:authenticated') // Broadcast an event that the driver has authenticated
setTimeout(async () => { // Dismiss the loader after successfull authentication
try {
const meDetails = await this.driverMe.getDriverMeInfo() // Get the profile information of the driver if
console.log(meDetails)
} catch (err) { console.log(err) }
this.backgroundLoader.dismiss();
this.loader = false
this.navCtrl.setRoot("HomePage")
this.menu.swipeEnable(true);
}, 1500);
}
} catch(err) { // If something goes wrong or an error occured
console.log(err)
this.backgroundLoader.dismiss();
this.loader = false
err.status == 401 || 422 // Something wrong in your authentication credentials
? this.alertMessage.alertMessage('Incorrect email or password', null)
: this.alertMessage.alertMessage('Something went wrong.', 'Please try again.') // Other errors not related to the data entry to be authenticated
}
}
The function does a basic authentication to send a post request to an API server and get the response token and put it on a Storage and use that token for every request that needs authentication middleware in the backend.
Actually there is no error in my code it works great. But if you look at the try and catch inside the setTimeout method. It looks uglier. The purpose of the try and catch is to catch an error for every promises but I am redeclaring it again inside the setTimeout function.
I'm not sure but I think this is happening because of the callback function on the setTimeout is a new async and await that's why it wont catch the error outside.
So my question really is there a way to handle this? To avoid redeclarations of try and catch inside a setTimeout method.
Appreciate if someone could help.
Thanks in advance.
Is there anyway to handle this using one try and catch

Categories

Resources