There are many cases in which developers need to consume APIs from the backend while using Create React App (CRA) to build an application. Because most client apps are hosted on different servers than the backend application, there are complications that arise as a result of requests being sent across both servers. CRA supports proxying to mitigate or entirely eliminate these issues.
In this article, we will discuss what a proxy server is, why you should use a proxy server in development, and uses cases for proxying requests in a React application. Then, we will implement a real life example of setting up a proxy server in React.
A proxy server is a system or application that acts as a conduit between a client application and the server when it requests resources.
The diagram above illustrates how proxy servers work. When you make a request to a server, it is routed through the proxy, which receives the response from the server and transmits the information back to the client.
You might be asking why it’s necessary to route some requests through a proxy before sending them to the server. The following scenarios need the use of a proxy server:
Need to protect your client from cross-site attacks? Proxy servers add an extra degree of protection by allowing server responses to be validated before being delivered to the client. They can be used as web filters and firewalls.
To avoid crashes, bandwidth must be conserved and server traffic must be regulated. Proxy servers can cache requests and server responses so that not all queries are transmitted to the server at the same time. This is typically done when dealing with static information and huge files.
Proxy servers are useful when client data must be protected or a request must be made anonymously. Proxy servers do not provide information to the server, such as the client’s location or IP address. Because the requests are not sent on a known network, this helps clients keep their data private by preventing hackers from intercepting important information.
Additionally, proxy servers can specify which requests are allowed and which are not. And finally, proxy servers can be used to log requests and the clients that make them within organizations that require it.
After understanding why proxy servers are required, it is critical to understand real-life scenarios in which proxy servers can be implemented. Some examples of proxying requests in React applications are listed below.
First is requesting HTTPS APIs in development (https://localhost
). Browsers have cross-origin limitations that block HTTPS API requests from HTTP sites running on localhost. Proxy servers can assist in redirecting requests to APIs without having to go via the browser’s default request options, which helps to evade several cross-origin limitations.
Second is fetching data from cross-origin APIs that don’t support CORs in web browsers. Certain APIs, regardless of the Hypertext Transfer Protocol, don’t support CORs for security concerns, and browsers impose same-origin policy to protect users from cross-site scripting (XSS). Proxy servers can be used to make API calls and then transmit the results to the web browser.
Finally, there is obtaining media resources from the server. A proxy server can be used to cache media files from the server, eliminating the need to send requests for such files to the server every time they are needed.
There are two common approaches of setting up proxy servers in React applications developed using CRA. We have the default CRA proxy option as well as the npm package http-proxy-middleware.
Please note that these methods are only effective in the development. I recommend following these guides to implement proxies in production:
First, we will set up the application with CRA so we can set up the proxy servers.
Make sure you have Node installed on your computer to use CRA. Then, in a new directory, start a terminal and run the following command:
npx create-react-app proxyclient && cd proxyclient
The command above will create a new directory called proxyclient
and set the terminal directory to /proxyclient
. The following folders and files should be present in the folder:
The package.json
file should also have a similar structure:
{ "name": "proxyclient", "version": "0.1.0", "private": true, "dependencies": { "@testing-library/jest-dom": "^5.16.2", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^13.5.0", "react": "^17.0.2", "react-dom": "^17.0.2", "react-scripts": "5.0.0", "web-vitals": "^2.1.4" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" }, "eslintConfig": { "extends": [ "react-app", "react-app/jest" ] }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] } }
Edit the App.js
file in the src
folder to include the following code:
import React, { useEffect } from 'react' const App = () => { useEffect(() => { fetch('https://google.com/search?q=javascript') .then(resp => { console.log(resp); console.log('======success======='); }) .catch(err => { console.log('======failure======='); console.log(err); }); }, []) return ( <div>App</div> ) } export default App
Above, the fetch
function is used to make a request to the cross-origin URL https://google.com/search?q=javascript
.
The application server should then be started so that we can view the response. Run the following command in the project directory’s terminal to start the application server:
npm start
By default, the above command will start listening on port 3000 on localhost
or 127.0.0.1
. If you open a browser and type “localhost:3000,” you should see something like this in the console:
To avoid this problem, we’ll define our CRA’s default proxy by including a proxy
field in the package.json
file like to this:
{ ..., "proxy": "https://www.google.com", ... }
Then, in the App.js
file, change the fetch request like so:
fetch('/search?q=proxy')
Above, we removed the origin and structure the request URL as if it were a same-origin request. The request should be successful, as shown in the browser console. It should output something like this:
Take notice of the URL in the response; it was transmitted to the browser as a same-origin, which resulted in http://localhost:3000/search?q=proxy
, and the CORs error was gone.
The browser receives the request and transmits it to the proxy server, which then redirects the request to the actual API server specified in the package.json
file.
We may also make requests to several servers by specifying the routes that should be used to target a specific domain. To accomplish this, we’ll structure our proxy
field in the package.json
file like so:
{ ..., "proxy": { "/search" : { "target" : "https://www.google.com", "changeOrigin" : true }, "/jobs" : { "target" : "https://stackoverflow.com", "changeOrigin" : true } } ... }
Above, we defined two paths
: /search
and /jobs
, which target two separate domains.
When we execute a fetch request on /jobs
, the browser sends the request as http://localhost:3000/jobs
, but the proxy server forwards it as https://stackoverflow.com/jobs
.
If you don’t want to use the default CRA proxy, you may use the http-proxy-middleware
npm package. Just note that this feature is available in [email protected]
or higher.
This package must be installed as a project dependency before it can be used. To do so, open a terminal and execute the following command in the project directory:
npm i http-proxy-middleware --save
Ensure you don’t have proxy defined in the package.json
file, then create a new file named setupProxy.js
in the src
directory. Add the following code snippet to the setupProxy.js
file:
const { createProxyMiddleware } = require('http-proxy-middleware'); const proxy = { target: 'https://www.google.com', changeOrigin: true } module.exports = function(app) { app.use( '/search', createProxyMiddleware(proxy) ); };
The code snippet above exports a function to the application so that the proxy middleware is registered to the application as soon as the development server starts up, without the need to import it into any file. Once the application is launched, it will start automatically.
We used createProxyMiddleware
from http-proxy-middleware
that we installed previously to register a proxy target for /search
.
In cases when there are several proxy targets, we simply call the app.use
function as follows:
const { createProxyMiddleware } = require('http-proxy-middleware'); const proxy = { target: 'https://www.google.com', changeOrigin: true } const proxy2 = { target: 'https://www.stackoverflow.com', changeOrigin: true, } module.exports = function(app) { app.use( '/search', createProxyMiddleware(proxy) ); app.use( '/jobs', createProxyMiddleware(proxy2) ); };
Above, we called the app.use
method after creating another object named proxy2
that included the proxy parameters of the other target domain in order to construct a proxy middleware.
You may expect better security, confidential requests, regulated requests, and other benefits when you use proxy servers in your client applications. Now that you know why and how to use a dev proxy server with CRA, I encourage you to put it to use in your next project.
Please feel free to ask questions or make suggestions in the comments section below.
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.
Handle frontend data discrepancies with eventual consistency using WebSockets, Docker Compose, and practical code examples.
Efficient initializing is crucial to smooth-running websites. One way to optimize that process is through lazy initialization in Rust 1.80.
2 Replies to "Why you should use a proxy server with Create React App"
How do you configure proxy for Production Environment ?
I’m getting this error when trying to do the object in package.json:
When specified, “proxy” in package.json must be a string.