Add Interceptors to instance of axios - reactjs

I'm trying to update my app token on axios interceptors, using React Native. I have this code to connect to API back-end:
const requestHelper = axios.create({
baseURL: "http://192.168.0.15:8000/api/",
headers: {
"Content-Type": "application/json",
Authorization: "token 3260b30bdbc19a5c4deed87327536e443c751d27",
},
});
const routes = {
accounts: {
getUser: () =>
requestHelper({
method: "get",
url: "accounts/detail/",
}),
.....
This is working but the token is hardcoded. I now need to update that token from AsyncStorage every time an API call is requested. I was trying to use Axios interceptors but is not working. These are my tests:
const requestHelper = axios.create({
baseURL: "http://192.168.0.15:8000/api/",
headers: {
"Content-Type": "application/json",
},
});
const createInterceptors = (instance) => {
instance.interceptors.request.use(
(config) => {
config.headers = {
Authorization: "token 3260b30bdbc19a5c4deed87327536e443c751d27",
};
return instance;
},
(error) => {
return Promise.reject(error);
}
);
return instance;
};
const routes = {
accounts: {
getUser: () =>
createInterceptors(
requestHelper({
method: "get",
url: "accounts/detail/",
})
),
....
The token is hardcoded here too, but for testing purposes. This tests raise an error:
[Unhandled promise rejection: TypeError: undefined is not an object (evaluating 'instance.interceptors.request')]
Does anyone know how this could be implemented?

I solved it. I have to add the interceptor function like this:
const requestHelper = axios.create({
baseURL: "http://192.168.0.15:8000/api/",
headers: {
"Content-Type": "application/json",
},
});
requestHelper.interceptors.request.use(async (config) => {
const token = await AsyncStorage.getItem("token");
config.headers = {
Authorization: "token " + token,
};
return config;
});

Related

Axios Post from react to express proxy server

I have created an express server in which I am implementing a graphQL request. The following block of code was taken from postman snippets of a successful request
const express = require("express"),
app = express(),
port = process.env.PORT || 4000,
cors = require("cors");
var axios = require('axios');
var data = JSON.stringify({
query: `mutation claimTask ($taskId: String!, $assignee: String) {
claimTask (taskId: $taskId, assignee: $assignee) {
id
name
taskDefinitionId
processName
creationTime
completionTime
assignee
variables {
id
name
value
previewValue
isValueTruncated
}
taskState
sortValues
isFirst
formKey
processDefinitionId
candidateGroups
}
}`,
variables: {"taskId":"22","assignee":"demo"}
});
var config = {
method: 'post',
url: 'http://[my_ip]/graphql',
headers: {
'Authorization': 'Bearer ey....',
'Content-Type': 'application/json',
'Cookie': 'TASKLIST-SESSION=..'
},
data : data
};
app.use(cors());
app.listen(port, () => console.log("Backend server live on " + port));
app.post("/api", (req, res) => {
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
res.send({ message: JSON.stringify(response.data) });
})
.catch(function (error) {
console.log(error);
res.send({ message: error });
});
})
Currently I am calling this request from a react app with a button like this:
Axios({
method: "POST",
url: "http://localhost:4000/api",
headers: {
"Content-Type": "application/json"
}
}).then(res => {
console.log(res.data.message);
});
For the next step I want to pass the variables from my react app instead of writing them directly as string to express. What is the right approach to achieve this?
I am using the express server to avoid cors related issues.
Any suggestions can be useful, thank you!
So you want to send an Axios POST from react. Something along those lines should work:
const handleSubmit = (e) => {
e.preventDefault();
const variables = {
taskId: ”22”,
userId: “demo”
};
axios.post("http://localhost:4000/api", variables).then((response) => {
console.log(response.status);
});
};
Inspired by https://blog.logrocket.com/understanding-axios-post-requests/

How to handle authorization headers on API call in React?

I'm trying to make a GET request to retrieve Total balance for a payment summary. I get a 401 unauthorized error on the console.
const getPay = () => {
Axios({
method: "GET",
url: `apiEndpoint/${variable}`,
headers: {
'Content-Type': 'application/json',
'x-access-token': "Available upon request"
}
})
.then((response) => {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
useEffect(() => {
getPay()
}, [])
The API docs states "Every request to any of the endpoints must contain the headers." The headers above were stated but I get an error 401(Unauthorized). please how do I go about this?
Just add Authorization in your headers
const getPay = () => {
Axios({
method: "GET",
url: `apiEndpoint/${variable}`,
headers: {
'Content-Type': 'application/json',
'x-access-token': "Available upon request",
Authorization: `Bearer YOUR_TOKEN`
}
})
.then((response) => {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
useEffect(() => {
getPay()
}, [])
Also, It is better to implement axios interceptors so that you dont have to pass headers in each call
// Request interceptor
API.interceptors.request.use(
async axiosConfig => {
const token = await getToken()
if (token && axiosConfig.headers) {
axiosConfig.headers.Authorization = `Bearer ${token}`
}
return axiosConfig
},
error => Promise.reject(error),
)

LocalStorage not working after storing token

I am storing JWT token in LocalStorage after Login success is dispatched and routing to next component. But the next component API call is not able to take LocalStored token.
If i refresh the page and click again, it is accepting the token. Dont know the issue.
This is Axios Instance and Login Dispatch respectively
const instance = axios.create({
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json; charset=utf-8',
'x-access-token': localStorage.getItem('accessToken'),
},
withCredentials: true,
validateStatus: (status) => status === 200
});
export function checkLogin(data, history) {
return function (dispatch) {
return dispatch(makeAPIRequest(loginAPI, data)).then(function (response) {
if (response.data.success == 1) {
localStorage.removeItem('accessToken')
localStorage.setItem('accessToken', response.data.data.token)
dispatch({ type: STORE_SESSION_TOKEN, authenticated: response.data.data.auth, token: response.data.data.token,userDetails: response.data.data.user });
history.push('/dashboard')
}
})
}
}
Expecting to take token from Localstorage from very next call from Dashboard. But that doesn't happen. says no token and redirects to Login
I think the problem is when you create the axios instance, the token is not available in localStorage.
You should try the default headers of axios:
export const AUTHORIZATION = 'authorization'
export const API = axios.create({
baseURL: `http://localhost:3000/api`
})
export const authorize = (token) => {
if (token) {
API.defaults.headers.Authorization = `Bearer ${token}`
localStorage.setItem(AUTHORIZATION, token)
}
}
export const unauthorize = () => {
delete API.defaults.headers.Authorization
localStorage.removeItem(AUTHORIZATION)
}
authorize(localStorage.getItem(AUTHORIZATION))
When you receive the token from the API in your actions, you have to save it to localStorage.
You need to get your header dynamically, because the token is not there while creating the instance and it might change later:
const JSON_HEADERS = {
'Accept': 'application/json',
'Content-Type': 'application/json; charset=utf-8'
};
const getTokenFromStorage = () => localStorage.getItem('token');
const getHeaders = () => getTokenFromStorage().then((token) => {
if (!token) {
return JSON_HEADERS;
}
return {
... JSON_HEADERS,
'x-access-token': token
};
});
export const makeAPIRequest = ({ method, url, data }) => {
return axios({
method,
url,
data,
headers: getHeaders()
});
}

(RN) Possible Unhandled Promise Rejection (id: 0): #Redux + axios

function requestService() {
return axios.create({
baseURL: userEndpoint,
headers: {
common: {
Accept: 'application/json',
}
}
}).then(response => {
return response.json();
}).catch(error => {
console.log('requestService', error);
});
}
module.exports = {
requestService
};
RequestService.js
import type { PromiseAction } from "./Types";
async function loadHopses(userId: number): PromiseAction {
const url = `hopses/user/${userId}`
const list = requestService().get(url);
await InteractionManager.runAfterInteractions();
return {
type: "LOADED_HOPSES",
list
};
}
module.exports = {
loadHopses
};
Action.js
this.props.dispatch(loadHopses(1));
App.js
export type PromiseAction = Promise<Action>;
Types.js
error is
Possible Unhandled Promise Rejection (id: 0):
TypeError: _axios2.default.create(...).then is not a function
TypeError: _axios2.default.create(...).then is not a function
I based on f8 facebook app and be converting parse to rest
What's wrong in this code?
please help..
axios.create returns an instance like this:
var instance = axios.create({
baseURL: 'https://some-domain.com/api/',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
These are the only valid methods for that.
axios#request(config)
axios#get(url[, config])
axios#delete(url[, config])
axios#head(url[, config])
axios#options(url[, config])
axios#post(url[, data[, config]])
axios#put(url[, data[, config]])
axios#patch(url[, data[, config]])
You can instead use it like this:
return axios.({
method: 'post',
baseURL: userEndpoint,
headers: {
common: {
Accept: 'application/json',
}
}
}).then(...).catch(...);
Using axios() instead of axios.create()

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