A proxy is something that acts on behalf of something else. Your best friend giving your attendance in the boring lecture you bunked during college is a real-life example of proxying.
When it comes to API development, a proxy is an interface between the client and the API server. The job of the interface is to proxy incoming requests to the real server.
But why you might need an API proxy in the first place?
- It could be possible that the real API server is external to your organization and unstable. Proxy can provide a more stable interface to the client
- The response from the API server might not be compatible with the client’s expectations and you want to modify the response in some form. For example, converting XML to JSON
- The real API server may be a temporary arrangement and you don’t want the clients to get impacted by any future changes
There are several uses of API proxy depending on the situation.
In this post, you will learn how to build a Node.js API Proxy using the http-proxy-middleware package.
1 – Node.js API Proxy Project Setup
First, you need to initialize the project by executing the below command in a project directory
$ npm init -y
This will generate a basic package.json
file with meta-data information about the project such as name
, version
, author
and scripts
.
Next, install a couple of packages for developing the Node.js API proxy.
$ npm install --save express http-proxy-middleware
express
is a minimalistic web framework you can use to build API endpoints. If interested, you can refer to this detailed post on getting started with Express.http-proxy-middleware
is a simple Node.js package to create an API proxy
After the package installation, define a start command for the project within the package.json
file. You can use this command to start the application.
Your project’s package.json
should look similar to the below example.
{
"name": "express-proxy-demo",
"version": "1.0.0",
"description": "Demo Application for Proxy Implementation in Node.js",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"author": "Saurabh Dashora",
"license": "ISC",
"dependencies": {
"express": "^4.18.2",
"http-proxy-middleware": "^2.0.6"
}
}
By the way, if you are interested in System Design and Backend topics, you’d love the Progressive Coder newsletter where I explain such concepts in a fun and interesting manner.
You can subscribe now for free from the below form.
2 – Creating a Node.js Proxy using http-proxy-middleware
Time to create the actual application.
The example application will proxy incoming requests to an API hosted elsewhere. For demonstration purpose, I recommend using the fake APIs hosted at JSONPlaceholder.
See below illustration:
Check the below code from the index.js
file that contains the logic for proxying requests.
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();
const PORT = 3000;
const HOST = "localhost";
const API_URL = "<https://jsonplaceholder.typicode.com>";
app.get("/status", (req, res, next) => {
res.send('This is a proxy service');
});
const proxyOptions = {
target: API_URL,
changeOrigin: true,
pathRewrite: {
[`^/api/posts`]: '/posts',
},
}
const proxy = createProxyMiddleware(proxyOptions);
app.use('/api/posts', proxy)
app.listen(PORT, HOST, () => {
console.log(`Proxy Started at ${HOST}:${PORT}`)
});
Let’s understand each step in the above program:
- The first segment of the code contains the import statements for
express
andhttp-proxy-middleware
. - The next statement creates an application instance using the call to
express()
function followed by declaring a few important constants such asPORT
,HOST
andAPI_URL
. - Implement an endpoint
/status
to describe the role of the application. This endpoint has nothing to do with proxying requests and provides a way to test our application. - Next, declare an object
proxyOptions
. This is a configuration object for our API proxy. It contains a few important propertiestarget
– It defines the target host where you want to proxy requests. In our case, this is thehttps://jsonplaceholder.typicode.com
changeOrigin
– This is set to true since we are proxying to a different origin.pathRewrite
– This is a very important property where you define the rules for rewriting the path. For example, the expression [^/api/posts
]: ‘/posts’ routes all incoming requests direct at/api/posts
to just/posts
. In other words, this will remove the/api
prefix from the path.
- After declaring the configuration object, create the proxy object by calling
createProxyMiddleware()
function with theproxyOptions
object as input. - Next, create a request handler for the path
/api/posts
and pass the proxy object as handler for the incoming request. - Finally, start the Node.js API Proxy server to listen on the port and host already declared earlier.
Running the Application
You can start the application using the command npm run start
.
> express-proxy-demo@1.0.0 start
> node index.js
[HPM] Proxy created: / -> <https://jsonplaceholder.typicode.com>
[HPM] Proxy rewrite rule created: "^/api/posts" ~> "/posts"
Proxy Started at localhost:3000
Messages about the proxy setup indicate that the proxy is configured properly. If you visit the URL http://localhost:3000/api/posts/1
in the browser, you will get the response from the JSONPlaceholder APIs as below:
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\\nsuscipit recusandae consequuntur expedita et cum\\nreprehenderit molestiae ut ut quas totam\\nnostrum rerum est autem sunt rem eveniet architecto"
}
This means that the Node.js API Proxy is doing its job by proxying requests to the mock APIs hosted by JSONPlaceholder.
3 – Node.js API Proxy Context Matching
The http-proxy-middleware
uses the path for proxying requests. For example, in the request http://localhost:3000/api/posts?title=test
, the section /api/posts
is the actual path.
There are various ways in which the context matching for the path takes place:
- Path Matching
createProxyMiddleware({...})
matches all paths. This means all requests will be proxied.createProxyMiddleware('/', {...})
also matches all paths.createProxyMiddleware('/api', {...})
only matches paths starting with/api
.
- Multiple Path Matching
createProxyMiddleware(['/api', '/test', '/otherpath'], {...})
can be used to match multiple paths to a particular proxy configuration
- Wildcard Path Matching
- For more fine grained control, you can also use wildcards to match paths.
createProxyMiddleware('**', {...})
matches any path and all requests are proxied.createProxyMiddleware('**/*.html', {...})
matches any path which ends with.html
.createProxyMiddleware('/api/**/*.html', {...})
matches requests ending with.html
within the overall path/api
.
- For more fine grained control, you can also use wildcards to match paths.
- Custom Path Matching For even greater control, you can also provide a custom function to match the path for the API Proxy. See below example:
const filter = function (pathname, req) { return pathname.match('^/api') && req.method === 'GET'; }; const apiProxy = createProxyMiddleware(filter, { target: '<https://jsonplaceholder.typicode.com>', });
In the above example, only GET requests to the path/api
are proxied.
Conclusion
With this post, you have built a very simple version of the Node.js API proxy. You can extend it further based on specific requirements.
The http-proxy-middleware
is a simple but powerful library to build a Node.js API Proxy server. The library provides several configurable properties to handle the proxy functionalities. However, there are many more options that you can leverage for your needs. Check out the official documentation for reference.
The code for this demo is available on Github.
After implementing an API Proxy, you may want to read more Forward Proxy implementation in Node.js.
If you found the post as useful, consider sharing it with friends and colleagues. In case of any queries, write them in the comments section below.
Anyways, before we end this post, a quick reminder about the Progressive Code Newsletter where I explain System Design & Backend concepts in a fun & interesting manner so that you never forget what you’ve learned.
I’m 100% sure you’d love it.
Subscribe now and see you over there.
2 Comments
LUCAS MARCOS SOUZA REIS · June 27, 2023 at 6:13 pm
Thank you buddy, it was of great help for me =D
Saurabh Dashora · June 28, 2023 at 2:24 am
Glad it was of help Lucas!