Why is http proxy middleware not working in React? - reactjs

This is my setupProxy.js:
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = (app) => {
app.use(
'http://localhost:8000',
createProxyMiddleware({
target: 'https://my-website.com', // Should request this url
changeOrigin: true,
})
);
};
And this is how I am calling the API:
makeAPICall = (method, headers, data) => {
let url = new Url('http://localhost:8000/api/get-data');
let requestOptions = {
method,
headers,
'body': data
}
return fetch(url, requestOptions);
}
But the API calls are going to the localhost and not the one that I mentioned in the setupProxy.
I know this is not right way to call apis when using proxy middleware, and we just need to provide a simple string in app.use like '/api1'. But I am not allowed to change the urls, just want to reroute them to new api.
What am I doing wrong here?
Edit: This is how I call makeAPICall function:
headers = {
'Content-Type': 'application/json',
'Authorization': `Token ${user.auth_token}`
}
makeAPICall('POST', headers, payload).then(data => handleData(data));

Related

Axios React cors issue on product

my third party axios requests works properly on local mode properly thanks to "http-proxy-middleware", but after i build and deploy it, axios requests gives homepage html as response.
setupProxy.js file
const { createProxyMiddleware } = require("http-proxy-middleware")
const cors=require("cors")
const express = require('express');
const app = express();
module.exports=app=>{
app.use(
createProxyMiddleware("/api",
{
target:"third-party-api-url",
secure:false,
changeOrigin:true
})
)
ApiFrontend.jsx file
const [apiData,setApiData]=useState("")
var data = JSON.stringify({
"MERCHANT": "****",
"MERCHANT_KEY": "*******************************"
});
var config = {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
data : data
};
useEffect(()=>{
axios("/api",config)
.then(function (response) {
setApiData(response.data);
})
.catch(function (error) {
console.log(error);
});
},[])
i tried node server with express and use;
app.use(cors({
origin: API_URL,
credentials: true
}));
but it gives the same response

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>

Downloading a video from an API in React using Axios creates an empty mp4 file

I have a backend api that returns a video (verified route in Postman) but when trying to implement a "download video" button, it downloads an empty file
I've tried multiple implementations with at best identical results but here is the current code:
const handleDownloadVideo = async () => {
const axios = require('axios');
const config = {
method: 'get',
url: `http://localhost:3001/api/v1/render/video/${UUID}/download/`,
headers: {
'Authorization': 'Bearer {token}',
'responseType': 'blob',
'maxContentLength': Infinity,
'maxBodyLength': Infinity
}
};
axios(config)
.then((response) => {
const link = document.createElement('a');
link.target = '_blank';
link.download = `${UUID}.mp4`;
link.href = URL.createObjectURL(new Blob([response.data], { type: "video/mp4" }));
link.click();
})
.catch(function (error) {
console.error(error);
});
};
I wouldn't expect this to be a difficult task and yet have been struggling with it for multiple days now. Can anybody explain what I'm doing wrong here?
Don't know if this might solve the problem, but your request config responseType, maxContentLength and maxBodyLength should be outside the header object.
const config = {
method: 'get',
url: `http://localhost:3001/api/v1/render/video/${UUID}/download/`,
responseType: 'blob',
maxContentLength: Infinity,
maxBodyLength: Infinity
headers: {
'Authorization': 'Bearer {token}'
}
};

Cookie-based authentication via REST API in react-admin

I'm new to react-admin. I already read through all the questions here in stackoverflow, and google'd for my question too, but did not find any useful solution.
I am setting up React-admin to replace an existing admin page for one of my projects. I use cookie-based authentication via REST API.
Is it possible (and if yes how?) to use it in react-admin? Can someone please lead me to the right direction?
Cheers!
It is possible of course. You just have to make fetch use cookies.
react-admin uses fetch to send http requests to your back-end. And fetch does not send cookies by default.
So to make fetch send cookies, you have to add the credentials: 'include' option for every fetch call the app makes.
(if your admin and api are not on the same domain, you will have to enable CORS on your back-end.)
See react-admin's doc for how to customize requests on the dataProvider here: https://github.com/marmelab/react-admin/blob/master/docs/Authentication.md#sending-credentials-to-the-api
import { fetchUtils, Admin, Resource } from 'react-admin';
import simpleRestProvider from 'ra-data-simple-rest';
const httpClient = (url, options = {}) => {
if (!options.headers) {
options.headers = new Headers({ Accept: 'application/json' });
}
const token = localStorage.getItem('token');
options.headers.set('Authorization', `Bearer ${token}`);
return fetchUtils.fetchJson(url, options);
}
const dataProvider = simpleRestProvider('http://localhost:3000', httpClient);
const App = () => (
<Admin dataProvider={dataProvider} authProvider={authProvider}>
...
</Admin>
);
You'll have to customize this to add options.credentials = 'include' like so :
const httpClient = (url, options = {}) => {
if (!options.headers) {
options.headers = new Headers({
Accept: 'application/json'
});
}
options.credentials = 'include';
return fetchUtils.fetchJson(url, options);
}
You will have to do the same thing for the authProvider.
Something like
// in src/authProvider.js
export default (type, params) => {
// called when the user attempts to log in
if (type === AUTH_LOGIN) {
const { username, password } = params;
const request = new Request(`${loginUri}`, {
method: 'POST',
body: JSON.stringify({ username: username, password }),
credentials: 'include',
headers: new Headers({ 'Content-Type': 'application/json' }),
});
return fetch(request)
.then(response => {
if (response.status < 200 || response.status >= 300) throw new Error(response.statusText);
localStorage.setItem('authenticated', true);
});
}
// called when the user clicks on the logout button

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