Prevent logging errors to console when using Axios interceptor - vue.js

I've implemented axios interceptor in my VueJs project, which looks like this:
axios.interceptors.response.use(
async (response) => {
return response;
},
async (error) => {
const originalRequest = error.config;
const isPublicUrl = [
'/account/login',
'/account/register'
].some(url=> originalRequest.url.includes(url));
if(isPublicUrl){
return Promise.reject(error);
}
if(error.response.status!==401){
return Promise.reject(error);
}
const token:TokenOpts = store.getters['auth/getToken'];
try{
const res = await AuthService.refreshToken(token);
const newToken = res.data;
store.dispatch('auth/refreshToken',newToken);
originalRequest.headers.Authorization = `Bearer ${newToken.accessToken}`;
const originalResponce = await axios.request(originalRequest);
return Promise.resolve(originalResponce);
}
catch(error){
return Promise.reject(error);
}
}
)
I can refresh my token and then send original request, here no problems.
My problem is that when I intercept an error, and end up inside error handler: async (error) => { HERE ... I already have an error in Chrome console. How can I prevent logging this error into the console?

This has nothing to do with VueJs. All errors will be logged in the console as that is the default option enabled in your browser. Follow this link to disable your network error messages. Suppress Chrome 'Failed to load resource' messages in console

Related

I only get an exception and not the error message from the server

I am currently programming a small login api and have implemented it with my react native project using axios request. But i have a problem now my server send an error status code with a message but in the react antive app it only comes to an exception with the status code and not with the message. How can I best solve this do I have to take the status code out of the server and just send text back or is there another solution?
My React Native api.js:
import axios from "axios";
import AsyncStorage from "#react-native-community/async-storage";
const instance = axios.create({
baseURL: "http://example.com",
});
instance.interceptors.request.use(
async (config) => {
const token = await AsyncStorage.getItem("token");
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(err) => {
return Promise.reject(err);
}
);
export default instance;
My React Native api trigger:
const Signup = async ({email, password}) => {
try{
const response = await myApi.post("/api/signup", { email, password });
if (response.data.token){
navigation.navigate('setup');
}else{
setError(response.data);
}
}catch (err){
console.log(err);
setError('Internet Error');
}
}
and my server response
return res.status(400).send({
message: "Email or password incorrect!",
});

node_modules/#tanstack/query-core/build/lib/mutation.js:153:10 in Mutation#execute react native expo

I'm buiding React Native Expo App with external rest api.
I have created reusable axios api call:
// axiosAPi.js
export const axiosApi = async (method, url, obj = {}) => {
try {
switch (method) {
case 'GET':
return await axios
.get(`${baseUrl}/${url}`, config)
.then((res) => res.data)
case 'POST':
return await axios
.post(`${baseUrl}/${url}`, obj, config)
.then((res) => res.data)
case 'PUT':
return await axios
.put(`${baseUrl}/${url}`, obj, config)
.then((res) => res.data)
case 'DELETE':
return await axios
.delete(`${baseUrl}/${url}`, config)
.then((res) => res.data)
}
} catch (error) {
throw error?.response?.data?.error
}
}
I have created a hook with login instance using react-query:
// api/index.js
export default function useApiHook() {
const login = useMutation((obj) => axiosApi('POST', `auth/login`, obj))
return { login }
}
Here is the implementation of login screen
// screens/login.js
const loginPostMutation = useApiHook()?.login
const submitHandler = (data) => {
loginPostMutation
?.mutateAsync(data)
?.then((res) => res)
.catch((err) => err)
}
When I send correct credentials is returns the data with no errors, but when I send incorrect credentials it returns the error + this warning in the console:
Invalid credentials
at node_modules/#tanstack/query-core/build/lib/mutation.js:153:10 in Mutation#execute
The line in question points towards react-query logging the error to the console in development mode. Invalid credentials is thus just an error that is returned from axios, very likely, a 401 - Unauthorized error.
You would very likely get the same error when making the axios request without react-query.

axios interceptor blocking api calls in redux saga

I have a react native project in which I'm calling some API's using redux-saga mechanism. Now when I added response interceptor for axios my saga api's are not working anymore. Does any knows how I can fix this?
here is the code for my axios instance class and response interceptor
const getLoggedInUser = async () => {
const savedUser = JSON.parse(
await getDataFromAsyncStorage(APP_CONSTANTS.SAVED_USER)
)
if (savedUser?.user_id != null) {
return savedUser
}
return null
}
const baseapi = axios.create({
baseURL: APP_CONSTANTS.BASE_URL,
headers: {},
})
baseapi.interceptors.request.use(
async (config) => {
const token = await getLoggedInUser()
const userId = token?.user_id
const authToken = token?.token
if (token) {
baseapi.defaults.headers.common['userId'] = token
baseapi.defaults.headers.common['token'] = authToken
}
return config
},
(error) => {
return Promise.reject(error)
}
)
// Response interceptor for API calls
baseapi.interceptors.response.use(
(response) => {
return response
},
async function (error) {
const originalRequest = error.config
if (error.response.status === 403 /* && !originalRequest._retry */) {
return baseapi(originalRequest)
}
return Promise.reject(error)
}
)
This is my saga class code and it fails directly when I add a response interceptor
function* getTopicList(action) {
try {
yield put({type: ACTION_TYPES.START_TOPIC_LIST})
const {payload} = action
const res = yield call(getAllTopicsOfBatch, payload)
if (res?.status == APP_CONSTANTS.SUCCESS_STATUS) {
yield put({
type: ACTION_TYPES.SET_TOPIC_LIST,
payload: {data: res?.data?.topics},
})
} else {
alert('OOPS Something went wrong! Please try again')
yield put({
type: ACTION_TYPES.ERROR_TOPIC_LIST,
payload: 'Something Went Wrong Please Try Again',
})
}
} catch (error) {
console.log('RESPONES error', error)
alert('OOPS Something went wrong! Please try again')
yield put({
type: ACTION_TYPES.ERROR_TOPIC_LIST,
payload: 'Something Went Wrong Please Try Again',
})
}
}
The code looks mostly fine, the only two things I found that are likely causing problems are:
In the request interceptors you are likely wrongly passing the whole token as userId instead of userId
baseapi.defaults.headers.common['userId'] = token // 'token' should be 'userId'
In the response interceptors error handler, you are not guaranteed to have 'response' property on error.
if (error.response.status === 403) // use error?.response
If neither of these things will fix your problem my guess is you have a problem in your endpoint and so you should examine the response errors you get to guide you.

react-native-community/asyncStorage removeItem causes program to behave weirdly

I have this little code snippet executed during the user logout.
async function logoutAction(props) {
removeUser();
props.logoutUser();
}
The function inside removeUser() is as :
export const removeUser = async () => {
try {
await AsyncStorage.removeItem(Constant.storage.user_data);
await AsyncStorage.removeItem(Constant.storage.token);
await AsyncStorage.removeItem(Constant.storage.notification_token);
return true;
} catch (exception) {
return false;
}
}
This clears user related data from local storage.
Similarly, props.logoutUser() is a reference call to reducer which sets loggedIn status to false.
I'm having this issue that if the removeUser() function is called once, the axios http requests do not enter the interceptors anymore and every request catches an error 'undefined'. If this method is removed though, everything works fine.
I can get it to working state then by removing the interceptors once, performing a request and then adding the interceptors again, which I found after hours of here and there.
My interceptors are:
export const requestInterceptor = axios.interceptors.request.use(
async config => {
const token = await getToken();
if (token != '') {
config.headers.Authorization = token;
}
console.log('axios request', config);
return config;
},
error => {
// console.warn('on request error')
return Promise.reject(error);
},
);
export const responseInterceptor = axios.interceptors.response.use(
function(response) {
console.log('axios response', response);
// console.warn('on response success', response.status)
return response;
},
async function(error) {
if (error.response.status === 401) {
//logout user
return;
}
return Promise.reject(error);
},
);
I am using the #react-native-community/AsyncStorage package for maintaining local storage. I suspect that the issue might be in the removeItem method but I'm unsure as the official docs don't contain the removeItem method, or in the interceptor which doesn't seem faulty to me anyways.
What am I doing wrong here?? Please show me some light..
Or maybe try add a await before removeUser(); ?
async function logoutAction(props) {
await removeUser();
props.logoutUser();
}
The issue was quite silly and did not even concern AsyncStorage or removeItem and as Matt Aft pointed out in the comment, it was due to the call for token in the interceptor after it had been removed while logging out. So, replacing
const token = await getToken();
if (token != '') {
config.headers.Authorization = token;
}
by
await getToken()
.then(token => {
config.headers.Authorization = token;
})
.catch(_ => {
console.log('no token');
});
in the interceptor and returning promise from the getToken method did the thing.
Thanks to Matt and 高鵬翔.

Error handling in Express using Axios for API call

I am trying to set up a basic express app to get some API data using axios. I want to do things the right way but I am a bit lost with error handling. Ideally, if there is an error I want to communicate it to users which I could do if the API call was within it the route. But how do you do it if it's a separate function?
axios call function using async:
const getForm = async () => {
try {
const config = {
method: 'get',
url: 'https://api.something.org/niceform'
}
}
const response = await axios(config)
return response
} catch (error) {
return error.message
}
}
express route:
app.get('/niceform', async (req, res) => {
try {
const data = await getForm()
res.send(data)
} catch (error) {
???
}
})
If I understand it correctly the getForm() function will return either the response or the error and then the route will send whatever comes back. But then what does the route's catch block do and how should I use it?
Is this setup considered to be a good practice?
Any advice would be appreciated, I am still learning.
The catch block can be removed from the getForm function. An error will be caught anyways in the get route.
const getForm = async () => {
const config = {
method: 'get',
url: 'https://api.something.org/niceform'
};
const response = await axios(config);
return response;
}
Or the error can be caught inside getForm, in order to do something in that catch block, and be thrown:
const getForm = async () => {
const config = {
method: 'get',
url: 'https://api.something.org/niceform'
};
try {
const response = await axios(config);
return response;
} catch (err) {
// log the error
// add extra information to the error
// else
// (see the attached answer)
throw err;
}
}
Consequently, in the catch block in the get route, an error can be responded:
app.get('/niceform', async (req, res) => {
try {
const data = await getForm();
res.send(data);
} catch (error) {
res.error(error);
}
})
Reference:
https://stackoverflow.com/a/42171508/3563737
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/throw