Vue 3 customize axios get,put,post - javascript

I want to customize my get,post,put functions with axios.
After doing the axios.create() operation, when I do the get operation, I want it to perform the then and catch operation there every time.
import axios from "axios";
export default (apiName = "") => {
let headers = {
"Content-Type": "application/json"
};
let token = JSON.parse(localStorage.getItem("token") || "{}");
if (token && token !== "") {
headers.Authorization = `Bearer ${token.AccessToken}`;
}
const instance = axios.create({
baseURL:
apiName === ""
? process.env.VUE_APP_API_URL
: process.env.VUE_APP_API_URL + apiName,
withCredentials: false,
headers: headers
});
return instance;
};
axios.post('/api/Export/CopyShippingPlan/', plan)
.then(handleResponse)
.catch((error) => {
console.log(error);
});
I want to define axios.post here after axios.create and have then and catch action wherever I call axios.post action. So I don't want to have to use then and catch where I use axios every time.

I think that you're looking for interceptors:
response interceptor will be called on every axios response
request interceptor will be called before every axios request
Example:
const ApiService = axios.create()
ApiService.interceptors.response.use(
config => {
//your code
return config
},
error => {
console.log(error)
return Promise.reject(error)
})
ApiService.interceptors.request.use(
config => {
//your code
return config
},
error => {
console.log(error)
return Promise.reject(error)
})
After setting them up you don't need to do anything special just call axios.get, axios.post, etc.

Related

How I can custom axios in Vue

I wrote a response with an axios interceptors and send the return value of this response to a js file named handleResponse. This js file takes the return value and returns a result to me. If I get an error, I have it drop to reject.
const instance = axios.create({
baseURL:
apiName === ""
? process.env.VUE_APP_API_URL
: process.env.VUE_APP_API_URL + apiName,
withCredentials: false,
headers: headers
});
instance.interceptors.response.use(
(response) => handleResponse(response),
(error) => console.log(error)
);
My handleResponse js file inside interceptors is as follows
export const handleResponse = (response) => {
return new Promise((resolve) => {
if (response.data["Success"]) resolve(response.data["Payload"]);
else {
let msg = "";
if (response.data["Information"]) msg = response.data["Information"];
showError(msg);
reject(response);
}
});
};
Here I make it fall into catch where I call the api when it drops to the reject operation.
const cancelStorageTransfer = () => {
return StorageTransferRequestService.cancelStorageTransfer(selectedStorageTransfer.value.Id)
.then(() => {
showSuccess("Transfer İptal İşlemi Başarıyla Gerçekleşti")
storageTransferRequestSummary()
}).catch(response => {
showError(response.data.Information)
})
}
I call the api here, but I don't want to use the catch. But when I don't use it, I get "Uncauth(in promise)" error on the log screen.
Here how can I do whether to use the catch at my own will?

Correct way to use axios interceptors

I want to add jwt token to my axiosinstance in Login.js but it is giving me error
IDX12729: Unable to decode the header '[PII is hidden. For more details, see https://aka.ms/IdentityModel/PII.]' as Base64Url encoded ...]
Here is my code:
Login.js
const printValues = e =>{
axiosInstance.post('/auth', data)
.then(res =>{
console.log("adding token");
const config = axiosInstance.interceptors.request.use(function (config) {
config.headers.Authorization = res.data.token;
return config;
});
axiosInstance.get('/User/GetUserByID/0', config)
.then(res =>{
//set user details
})
.catch(err =>{
console.log(err);
})
}
use doesn't return a config for you to pass into requests. As long as you are using the same instance, the config would get altered.
axiosInstance.interceptors.request.use(function (config) {
config.headers.Authorization = res.data.token;
return config;
});
axiosInstance.get('/User/GetUserByID/0')
.then(res =>{
//set user details
})
.catch(err =>{
console.log(err);
})
First, don't define interceptors within a response handler. That means you'll be adding an interceptor every time you make that request.
Typically you would keep your token state and interceptor separate from other application code. Wherever you created your axiosInstance is a good candidate.
For example...
import axios from "axios"
const axiosInstance = axios.create({
// ..
})
const token = null // initial state
axiosInstance.interceptors.request.use(async config => {
if (!token) {
// note, use a separate axios instance for this request
const { data } = await axios.post("/auth", dataFromSomewhere)
token = data.token
}
config.headers.Authorization = `Bearer ${token}` // you may need "Bearer" here
return config
})
Now you can use axiosInstance to make requests and it will transparently resolve your authorisation token if required before continuing.
const printValues = e => {
axiosInstance.get("/User/GetUserByID/0")
.then(res =>{
//set user details
})
.catch(err =>{
console.log(err);
})
}

Cannot set headers after they are sent to the client axios next.js

Same question on GitHub - https://github.com/axios/axios/issues/2743
I have Axios in my Next.js project and sometimes I get an error due to interceptor when return the Promise.reject.
Error: Cannot set headers after they are sent to the client.
I encounter this problem when I make a request in getInitialProps. This happens very rarely when I restart the PC and open the page again.
Axios instance:
const instance = axios.create({
baseURL: 'https://my-api.com',
withCredentials: true,
headers: {
'X-Requested-With': 'XMLHttpRequest',
},
})
instance.interceptors.response.use(undefined, error => {
if (error.response.status === 401) {
console.log("UNAUTHORIZED")
}
return Promise.reject(error) // <-- this cause the problem
})
Next.js Page example:
const Index = ({myData}) => {
return data.map(...)
}
Index.getInitialProps = async ({req}) => {
let myData
try {
const res = await API.get('/my-request', {
headers: req ? { cookie: req.headers.cookie } : undefined, //setting cookie
})
myData = res.data
} catch (e) {}
return {myData}
}
This problem disappeared when I upgraded Axios 0.19.0 to 0.19.2 ¯_(ツ)_/¯

Axios interceptor request to refresh id token when expired in VueJs

I want to use axios interceptor before every axios call to pass idToken as authorization header with all the axios calls and I want to refresh the idToken if it has expired before any call.
I am using the following code:
axios.interceptors.request.use(function(config) {
var idToken = getIdToken()
var refreshToken = {
"refreshToken" : getRefreshToken()
}
if(isTokenExpired(idToken)){
console.log("==============Reloading")
refresh(refreshToken).then(response=>{
setIdToken(response.idToken)
setAccessToken(response.accessToken)
})
idToken = getIdToken()
config.headers.Authorization = `${idToken}`;
}
else{
config.headers.Authorization = `${idToken}`;
}
return config;
}, function(err) {
return Promise.reject(err);
});
It works fine till the time idToken is valid. When the idToken expires it gets in an infinite loop and the page hangs. Please help me with this. The refresh() which call the refresh API looks like this:
function refresh(refreshToken) {
const url = `${BASE_URL}/user/refresh`;
return axios.post(url,JSON.stringify(refreshToken))
.then(response =>response.data.data)
.catch(e => {
console.log(e);
});
}
I had some similar problem and creating new axios instance to perform refresh token api call resolved the problem (new AXIOS instance is not resolved by defined axios.interceptors.request.use) (of course below code is just a simple example).
Remember to save original request and process it after token has been refreshed:
F.ex my http-common.js
import axios from 'axios'
const AXIOS = axios.create()
export default AXIOS
...
in App.vue:
axios.interceptors.request.use((config) => {
let originalRequest = config
if (helper.isTokenExpired(this.$store.getters.tokenInfo)) {
return this.refreshToken(this.$store.getters.jwt).then((response) => {
localStorage.setItem('token', response.data.token)
originalRequest.headers.Authorization = response.data.token
return Promise.resolve(originalRequest)
})
}
return config
}, (err) => {
return Promise.reject(err)
})
and the refresh token method:
refreshToken (token) {
const payload = {
token: token
}
const headers = {
'Content-Type': 'application/json'
}
return new Promise((resolve, reject) => {
return AXIOS.post('/api/auth/token/refresh/', payload, { headers: headers }).then((response) => {
resolve(response)
}).catch((error) => {
reject(error)
})
})
}
}

localstorage.getitem('key') sometimes returns null - in a react app

this is a very weird problem! I'm trying to build a login form which sets a JWT token in localstorage. Other forms then use that token to post requests. I can see the token in my console.log just fine, but sometimes (like 3 out of 5 times), when I am setting localstorage.getitem('idToken'), it shows as null. This behavior most noticeably happens when I remove the console.log(idToken) from my loginUser() function (code in actions.js file - given below). What am I doing wrong? my app is built using React/Redux.
action.js
export function loginUser(creds) {
const data = querystring.stringify({_username: creds.username, _password: creds.password});
let config = {
method: 'POST',
headers: { 'Content-Type':'application/x-www-form-urlencoded' },
body: data
};
return dispatch => {
// We dispatch requestLogin to kickoff the call to the API
dispatch(requestLogin(creds));
return fetch(BASE_URL+'login_check', config)
.then(response =>
response.json().then(user => ({ user, response }))
).then(({ user, response }) => {
if (!response.ok) {
// If there was a problem, we want to
// dispatch the error condition
dispatch(loginError(user.message));
return Promise.reject(user)
} else {
localStorage.setItem('idToken', user.token);
let token = localStorage.getItem('idToken')
console.log(token);
// if I remove this log, my token is returned as null during post.
dispatch(receiveLogin(user));
}
}).catch(err => console.log("Error: ", err))
}
}
here's my POST request:
import axios from 'axios';
import {BASE_URL} from './middleware/api';
import {reset} from 'redux-form';
let token = localStorage.getItem('idToken');
const AuthStr = 'Bearer '.concat(token);
let headers ={
headers: { 'Content-Type':'application/json','Authorization' : AuthStr }
};
export default (async function showResults(values, dispatch) {
console.log(AuthStr);
axios.post(BASE_URL + 'human/new', values, headers)
.then(function (response) {
console.log(response);
alert("Your submit was successful");
//dispatch(reset('wizard'));
}).catch(function (error) {
console.log(error.response);
alert(error.response.statusText);
});
});
This GET request works everytime, BTW:
getHouses = (e) => {
let token = localStorage.getItem('idToken') || null;
const AuthStr = 'Bearer '.concat(token);
axios.get(BASE_URL + 'household/list', { headers: { Authorization: AuthStr } }).then((response) =>
{
let myData = response.data;
let list = [];
let key =[];
for (let i = 0; i < myData._embedded.length; i++) {
let embedded = myData._embedded[i];
list.push(embedded.friendlyName);
key.push(embedded.id);
}
this.setState({data: list, key: key});
})
.catch((error) => {
console.log('error' + error);
});
}
I'm at my wit's end! Please help!
The localStorage.setItem() is a asynchronous task, and sometimes you run let token = localStorage.getItem('idToken') just after the setItem will fail, so you get a null, so please put the getItem operation some later, have a try, it will be different :
setTimeout(function() {
let token = localStorage.getItem('idToken');
dispatch(receiveLogin(user));
}, 50);
Move your token logic (i.e. localStorage.getItem('idToken');) inside the exported function and it should work
export default (async function showResults(values, dispatch) {
let token = localStorage.getItem('idToken');
const AuthStr = 'Bearer '.concat(token);
let headers ={
headers: { 'Content-Type':'application/json','Authorization' : AuthStr
}
};
axios.post(BASE_URL + 'human/new', values, headers)...
There can't be a case where you set a key value in localstorage and then it returns you null, immediately in the next line.
localStorage.setItem('idToken', user.token);
let token = localStorage.getItem('idToken');
This will only happen if your user.token value is null.
Maybe the case here is your thennable function not returning value to your next then like this:
....
.then(response =>
// return response to your next then function
// this will be passed to next then function as params
return response.json();
).then(({ user, response }) => {
....
Make a function whose return the value or a default value
const [hideTyC, setHideTyC] = useState(false);
const loadTyCFlag = (): any => {
if (
localStorage.getItem("tyc") !== null ||
localStorage.getItem("tyc") !== undefined
) {
return localStorage.getItem("tyc") || false;
}
};
useIonViewDidEnter(() => {
hideTabBar();
setHideTyC(loadTyCFlag());
});

Categories

Resources