How to properly set axios default headers - reactjs

I'm using reactjs for my project but I have one issue, in config.js file where i set my global axios configurations, I'm setting default headers for axios requests but when i make axios request it does not send those headers in requests.
config.js
import axios from 'axios';
const instance = axios.create({
baseURL: 'URL/api'
});
export const setAuthToken = (token) => {
if (token) {
// Apply to every request
instance.defaults.headers.common['Authorization'] = 'Bearer ' + token;
} else {
// Delete auth header
delete instance.defaults.headers.common['Authorization'];
}
};
export default instance;
Login.js
import axios from '../../../config';
import { setAuthToken } from '../../../config';
axios
.post('/auth/signin', {
username: email,
password: password
})
.then((res) => {
setCurrentUser(res.data);
setAuthToken(res.data.accessToken);
setLoading(false);
})
.catch((err) => {
console.log(err);
setLoading(false);
setError(true);
});

You can use axios interceptors for this task.
1-) Inside the successfull login, put the retrieved token to the localStorage. Remove setAuthToken line.
.then((res) => {
setCurrentUser(res.data);
localStorage.setItem("token", res.data.accessToken);
setLoading(false);
})
2-) Add this interceptor to your axios instance.
const instance = axios.create({
baseURL: 'URL/api'
});
instance.interceptors.request.use(
function(config) {
const token = localStorage.getItem("token");
if (token) {
config.headers["Authorization"] = 'Bearer ' + token;
}
return config;
},
function(error) {
return Promise.reject(error);
}
);

I had to create the header object structure within the instance for global header overriding to work:
The code snippet below does not working (but it does not raise any error); global header is used when using the instance:
// Index.js
axios.defaults.headers.common['Authorization'] = 'AUTH_TOKEN';
// myAxios.js
const instance = axios.create({
baseURL: 'https://jsonplaceholder.typicode.com'
});
instance.defaults.headers.common['Authorization'] = 'AUTH_TOKEN_FROM_INSTANCE';
This does work, instance header overrides the global default:
// Index.js
axios.defaults.headers.common['Authorization'] = 'AUTH_TOKEN';
// myAxios.js
const instance = axios.create({
baseURL: 'https://jsonplaceholder.typicode.com',
headers: {
common: {
Authorization: 'AUTH_TOKEN_FROM_INSTANCE'
}
}
});
It seems to me that this object structure should be created by default when using #create.
===========================================================================
Additionally, if you want to unset the header don't use delete. Here's a test:
it('should remove default headers when config indicates', function (done) {
var instance = axios.create();
instance.defaults.headers.common['Content-Type'] = 'application/json';
instance.post('/foo/bar/', {
firstName: 'foo',
lastName: 'bar'
}, {
headers: {
'Content-Type': null
}
});
getAjaxRequest().then(function (request) {
testHeaderValue(request.requestHeaders, 'Content-Type', null);
done();
});
});

You can add axios headers token by default..Just follow 2 steps
#Step - #1.
Create axios instance -
const API_BASE_URL = "http://127.0.0.1:8000/api";
export const axiosPrivate = axios.create({
baseURL: API_BASE_URL,
timeout: 60000
});
#Step - #2.
Set default header before sent api request
axiosPrivate.interceptors.request.use((request) => {
// Do something before request is sent
request.headers = {
'Authorization': 'Bearer ' + localStorage.getItem('token'),
};
return request;
}, (error) => Promise.reject(error));

Related

How to pass accessToken to Axios interceptor without Redux

I am trying to authorize a Next app using the existing Nodejs backend using a manual JWT strategy.
My backend issues an access token, and I'm trying to sign each request with accessToken using axios.interceptor where I set Bearer ${token}
// utils/axios.ts
const axiosPrivate = axios.create({
baseURL: process.env.NEXT_PUBLIC_API_BASE_URL,
timeout: 1000,
withCredentials: true,
headers: {
'Content-Type': 'application/json',
},
});
axiosPrivate.interceptors.request.use(
(config: AxiosRequestConfig): AxiosRequestConfig => {
if (config.headers === undefined) {
config.headers = {};
}
// no way to access sessionStorage or document.cookies
config.headers['Authorization'] = `Bearer ${accessToken}`
return config;
}
);
export { axiosPrivate }
My question is if there is some way to grab access token without Redux?
I want it in the interceptor because it will let me do SSR like that:
// pages/dashboard.tsx
export const getServerSideProps: GetServerSideProps = async (context) => {
const res = await axiosPrivate.get('/dashboard'); // request already signed
return {
props: {
dashboard: res.data,
},
};
};
You can pass the accessToken in the params for the axios request.
<code>await axiosPrivate.get('/dashboard', {
params: {
accessToken
}
});
</code>

how to pass token to local storage with axios

I created an Axios instance to set up the baseURL and the headers. The header also needs to contain the token for authorization.
export const instance = axios.create({
baseURL: import.meta.env.VITE_API_URL,
headers: {
Authorization: `Bearer ${localStorage.getItem(LOCAL_STORAGE_API_KEY)}`
},
validateStatus: () => true
});
when the user logs in, I call an API to get some data related to the user using useQuery. When I log in, I try to store the token in local storage, but I think I'm doing something wrong and I get an error from the backend.
export const LOCAL_STORAGE_API_KEY = 'token';
import { instance } from './ApiProvider';
import { LOCAL_STORAGE_API_KEY } from '#/helpers/constants';
export const loginActions = async ({ email, password }) => {
const response = instance
.post('/api/v1/Auth/Login', {
user: {
email: email,
password: password
}
})
.then((data) => {
instance.defaults.headers.post[
'Authorization'
] = `Bearer ${localStorage.getItem('LOCAL_STORAGE_API_KEY')}`;
return data;
});
return response;
};
The problem is that instance is created before you have the auth header value available and hence on subsequent call it will pass the value as undefined.
You can use axios interceptors for this task.
instance.interceptors.request.use(
function(config) {
const token = localStorage.getItem("LOCAL_STORAGE_API_KEY");
if (token) {
config.headers["Authorization"] = 'Bearer ' + token;
}
return config;
},
function(error) {
return Promise.reject(error);
}
);

how to call `localStorage.getItem ` immediately after render

first i use localStorage.setItem to save a token that i've taken from api and set it as header in my axios
i need to use local.storage.getItem() to read the data and then set it as header
so there is another action which sends request ,takes the token and saves it to local storage by localStorage.setItem() and replaces the browser history to where i'm calling the action that needs the token ,but it shows 404 error with the only first error which means only at the first time and if i close the page and open it again it works fine
I'll show the code step by step
here is my code where i want to use the token
import axios from 'axios';
const token = localStorage.getItem('token')//here doesn't get it and shows 404 error from API i refresh the page for second time or after
export default axios.create({
headers:{"Authorization": `Bearer ${token}`}
})
here is my action where i get the token with diffrent instance of axios which has no header
export const sendCode = (phone, code) => async dispatch => {
dispatch({ type: LOADING_STATE })
const response =
await loginApi.post(baseurl + "Auth/Checkcode", {
phone: phone,
code: code
},
)
dispatch({ type: SEND_CODE, payload: response.data });
if (response.data.success === true) {
history.replace('/home')
localStorage.setItem("token", response.data.obj.token)
}
and finally here is the action that i call it with the instance that has header
export const getHomeInfo = () => async dispatch => {
dispatch({type:LOADING_STATE})
const response = await homeAPI.get(baseurl + "Home/GetList")//homeAPI is the instance that has header
dispatch({ type: GET_HOME_INFO, payload: response.data })
};
import axios from 'axios';
const token = localStorage.getItem('token')
export default axios.create({
headers:{"Authorization": `Bearer ${token}`}
})
Here, token will be fetch once when the js file is bundled, you have to refetch it each time :
import axios from 'axios';
const getHeaders = () => {
const token = localStorage.getItem('token')
return {"Authorization": `Bearer ${token}`}
}
export default axios.create({
headers: getHeaders()
})
EDIT : The code above does not work since axios.create() is called only once, if you need dynamic headers, you should add an interceptor which will be called before each request :
const axiosInstance = axios.create()
axiosInstance.interceptors.request.use(
(config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.authorization = `Bearer ${token}`;
}
return config;
},
(error) => Promise.reject(error),
);
export default axiosInstance

How to assign headers in axios.all method React Native

I'm getting data from multiple api's and rendering into <Pickers /> but the issue is that I'm unable to assign headers for Auth in this axios.all method. Kindly provide me a solution or mistake if I'm doing.
axios.all([
axios.get(this.apiUrl + '/case/GetCaseType'),
axios.get(this.apiUrl + '/case/GetCasePriority')
], { headers: { 'authorization': 'bearer ' + this.state.jwtToken } })
.then(axios.spread(( response2, response3) => {
console.log('Response 1: ', response1.data.retrn);
console.log('Response 2: ', response2.data.retrn);
console.log('Response 3: ', response3.data.retrn);
this.hideLoader();
})).catch(error => console.log(error.response));
You can create a service file to handle all request for GET or POST, FIle for handling GET request with Autherization header is given belwo
GetService.js
import axios from 'axios';
let constant = {
baseurl:'https://www.sampleurl.com/'
};
let config = {
headers: {
'Content-Type': 'multipart/form-data',
'Accept': 'application/json'
}
};
export const GetService = (data,Path,jwtKey) => {
// jwtKey is null then get request will be send without header, ie for public urls
if(jwtKey != ''){
axios.defaults.headers.common['Authorization'] = 'Bearer '+jwtKey;
}
try{
return axios.get(
constant.baseUrl+'api/'+Path,
data,
config
);
}catch(error){
console.warn(error);
}
}
You can use the configs and create instance to set common things like url, token, timeout etc
import axios from 'axios';
const http = axios.create({
baseURL: this.url,
timeout: 5000
});
http.defaults.headers.common['authorization'] = `bearer ${this.state.jwtToken}`
export async function yourAPIcallMethod(){
try{
const [res1,res2] = await http.all([getOneThing(), getOtherThing()]);
//when all responses arrive then below will run
//res1.data and res2.data will have your returned data
console.log(res1.data, res2.data)
//i will simply return them
return {One: res1.data, Two: res2.data}
}
catch(error){
console.error(error.message || "your message")
}
}
This can be used in your component.jsx like
import {yourAPIcallMethod} from './httpService';
async componentDidMount(){
const data = await yourAPIcallMethod();
this.setState({One: data.One, Two: data.Two})
}
You can see and learn more on github axios.

Sending the bearer token with axios

In my react app i am using axios to perform the REST api requests.
But it's unable to send the Authorization header with the request.
Here is my code:
tokenPayload() {
let config = {
headers: {
'Authorization': 'Bearer ' + validToken()
}
}
Axios.post(
'http://localhost:8000/api/v1/get_token_payloads',
config
)
.then( ( response ) => {
console.log( response )
} )
.catch()
}
Here the validToken() method would simply return the token from browser storage.
All requests are having a 500 error response saying that
The token could not be parsed from the request
from the back-end.
How to send the authorization header with each requests? Would you recommend any other module with react?
const config = {
headers: { Authorization: `Bearer ${token}` }
};
const bodyParameters = {
key: "value"
};
Axios.post(
'http://localhost:8000/api/v1/get_token_payloads',
bodyParameters,
config
).then(console.log).catch(console.log);
The first parameter is the URL.
The second is the JSON body that will be sent along your request.
The third parameter are the headers (among other things). Which is JSON as well.
Here is a unique way of setting Authorization token in axios. Setting configuration to every axios call is not a good idea and you can change the default Authorization token by:
import axios from 'axios';
axios.defaults.baseURL = 'http://localhost:1010/'
axios.defaults.headers.common = {'Authorization': `bearer ${token}`}
export default axios;
Some API require bearer to be written as Bearer, so you can do:
axios.defaults.headers.common = {'Authorization': `Bearer ${token}`}
Now you don't need to set configuration to every API call. Now Authorization token is set to every axios call.
You can create config once and use it everywhere.
const instance = axios.create({
baseURL: 'https://example.com/api/',
timeout: 1000,
headers: {'Authorization': 'Bearer '+token}
});
instance.get('/path')
.then(response => {
return response.data;
})
The second parameter of axios.post is data (not config). config is the third parameter. Please see this for details: https://github.com/mzabriskie/axios#axiosposturl-data-config
By using Axios interceptor:
const service = axios.create({
timeout: 20000 // request timeout
});
// request interceptor
service.interceptors.request.use(
config => {
// Do something before request is sent
config.headers["Authorization"] = "bearer " + getToken();
return config;
},
error => {
Promise.reject(error);
}
);
If you want to some data after passing token in header so that try this code
const api = 'your api';
const token = JSON.parse(sessionStorage.getItem('data'));
const token = user.data.id; /*take only token and save in token variable*/
axios.get(api , { headers: {"Authorization" : `Bearer ${token}`} })
.then(res => {
console.log(res.data);
.catch((error) => {
console.log(error)
});
Just in case someone faced the same issue.
The issue here is when passing the header without data, the header's configuration will be in the payload data, So I needed to pass null instead of data then set the header's configuration.
const config = {
headers: {
"Content-type": "application/json",
"Authorization": `Bearer ${Cookies.get("jwt")}`,
},
};
axios.get(`${BASE_URL}`, null, config)
This works and I need to set the token only once in my app.js:
axios.defaults.headers.common = {
'Authorization': 'Bearer ' + token
};
Then I can make requests in my components without setting the header again.
"axios": "^0.19.0",
I use a separate file to init axios instance and at the same time, I add intercepters to it. Then in each call, the intercepter will add the token to the request header for me.
import axios from 'axios';
import { getToken } from '../hooks/useToken';
const axiosInstance = axios.create({
baseURL: process.env.REACT_APP_BASE_URL,
});
axiosInstance.interceptors.request.use(
(config) => {
const token = getToken();
const auth = token ? `Bearer ${token}` : '';
config.headers.common['Authorization'] = auth;
return config;
},
(error) => Promise.reject(error),
);
export default axiosInstance;
Here is how I use it in the service file.
import { CancelToken } from 'axios';
import { ToolResponse } from '../types/Tool';
import axiosInstance from './axios';
export const getTools = (cancelToken: CancelToken): Promise<ToolResponse> => {
return axiosInstance.get('tool', { cancelToken });
};
// usetoken is hook i mad it
export const useToken = () => {
return JSON.parse(localStorage.getItem('user')).token || ''
}
const token = useToken();
const axiosIntance = axios.create({
baseURL: api,
headers: {
'Authorization':`Bearer ${token}`
}
});
axiosIntance.interceptors.request.use((req) => {
if(token){
req.headers.Authorization = `Bearer ${token}`;
}
return req;
})
If you are sending a post request with empty data remember to always set the second parameter to either empty object or empty string just as in the example below. e.g: axios.post('your-end-point-url-here', '', config)
if you don't set it axios will assume that whatever you are passing as the second parameter is a formData
const config = {
headers: { Authorization: `Bearer ${storage.getToken()}` }
};
axios
.post('http://localhost:8000/api/v1/get_token_payloads', {}, config)
.then(({ data: isData }) => {
console.log(isData);
})
.catch(error => {
console.log(error);
});
You must mention the 2nd parameter body for the post request even if it is empty, try this :
tokenPayload() {
let config = {
headers: {
'Authorization': 'Bearer ' + validToken()
}
}
Axios.post(
'http://localhost:8000/api/v1/get_token_payloads',
// empty body
{},
config
)
.then( (response) => {
console.log(response)
} )
.catch()
}
You can try configuring the header like this:
const headers = {"Content-Type": "text/plain", "x-access-token": token}
You can use interceptors in axios:
axios.interceptors.request.use(function (config) {
// Do something before request is sent
return config;
}, function (error) {
// Do something with request error
return Promise.reject(error);
});
More on that you can find here: https://axios-http.com/docs/interceptors
there are a lot of good solution but I use this
let token=localStorage.getItem("token");
var myAxios=axios.create({
baseURL: 'https://localhost:5001',
timeout: 700,
headers: {'Authorization': `bearer ${token}`}
});
export default myAxios;
then i import myaxios to my file and
myAxios.get("sth")
axios by itself comes with two useful "methods" the interceptors that are none but middlewares between the request and the response. so if on each request you want to send the token. Use the interceptor.request.
I made apackage that helps you out:
$ npm i axios-es6-class
Now you can use axios as class
export class UserApi extends Api {
constructor (config) {
super(config);
// this middleware is been called right before the http request is made.
this.interceptors.request.use(param => {
return {
...param,
defaults: {
headers: {
...param.headers,
"Authorization": `Bearer ${this.getToken()}`
},
}
}
});
this.login = this.login.bind(this);
this.getSome = this.getSome.bind(this);
}
login (credentials) {
return this.post("/end-point", {...credentials})
.then(response => this.setToken(response.data))
.catch(this.error);
}
getSome () {
return this.get("/end-point")
.then(this.success)
.catch(this.error);
}
}
I mean the implementation of the middleware depends on you, or if you prefer to create your own axios-es6-class
https://medium.com/#enetoOlveda/how-to-use-axios-typescript-like-a-pro-7c882f71e34a
it is the medium post where it came from

Resources