Building scalable and flexible web applications now relies heavily on APIs in modern web development. APIs are used to communicate with databases, other online apps, and third-party services. To handle certain functionality within their application, developers occasionally need to construct their own API endpoints.
In this post, one of the most well-liked server-side rendering frameworks for React, NextJS, is used to develop an API proxy.
An API proxy is a third-party server that stands in between a client and an API server and relays requests to the latter.
In other words, a proxy is an intermediary server that acts as a gateway between a user and the internet. It allows users to access websites and services while maintaining their anonymity and protecting their privacy.
Developers can take advantage of Next.JS's robust server-side rendering features to build scalable and effective API endpoints by setting up an API proxy.
If you are making calls to api directly from client-side code base, then call’s to api logged on the client’s browser with actual api end-point:
Using an API proxy in Next.JS can help simplify the process of making API requests from your client-side code and it’s also help you to avoid CORS issues and improve the security of your web application. With just a few lines of code, you can create a proxy that forwards requests to your API and returns the response to your client-side code. Let's start now!
Now we will explore the use of proxy in Next.JS applications.
Implementing a proxy in a Next.js app
There are many ways to implement the API proxy in Next.JS applications:
- Implement API Proxy using next.config.js
An incoming request path can be mapped to a different
destination path using Next.config.js rewrites.
Rewrites serve as a URL proxy and conceal the destination path, giving the impression that the user hasn't moved around the website. Redirects, on the other hand, show the URL changes and reroute to a new page. You can use the rewrites key in next.config.js to use rewrites.
I have used the
Sitecore’s PLAY! Summit Demo to implement the next.config.js rewrite.
Here we're using Next.js rewrites to match any requests to:
-
sitecore/api/* and rewrite them to {jssConfig.sitecoreApiHost}/sitecore/api/*, where jssConfig.sitecoreApiHost is your Content Delivery node HOST Name
-
/api/userdata/ redirected to https://dummyapi.io/data/v1/ which is an external API
-
Also next.js rewrites to match any requests to /api/proxydata/* and rewrite them to /apiProxy/*. Then, we're using server middleware (http-proxy-middleware) to apply the API proxy middleware to all requests matching /apiProxy/*
-
To implement API Proxy using Next.js rewrites in Sitecore Next.JS application, I have updated the Sitecore Next.JS application next.js.config file:
async rewrites() {
// When in connected mode we want to proxy Sitecore paths off to Sitecore
return [
// API endpoints
{
source: '/sitecore/api/:path*',
destination: `${jssConfig.sitecoreApiHost}/sitecore/api/:path*`,
},
// media items
{
source: '/-/:path*',
destination: `${jssConfig.sitecoreApiHost}/-/:path*`,
},
// visitor identification
{
source: '/layouts/system/:path*',
destination: `${jssConfig.sitecoreApiHost}/layouts/system/:path*`,
},
// External user details
{
source: '/api/userdata/:slug*',
destination: `https://dummyapi.io/data/v1/:slug*`,
},
// External API > user details
{
source: '/api/proxydata/:path*',
destination: `/apiProxy/:path*`,
},
];
},
-
To use API Proxy in Sitecore Next.JS application, I have created the Non-Sitecore page in Sitecore Next.JS application at \src\rendering\src\pages\integrations\users\index.tsx. In this file I have used the proxy api call /api/userdata/ for actual third-party api call https://dummyapi.io/data/v1/ inside the Next.js, getLayout function that allows you to dynamically set the layout for a specific page or group of pages. This allows you to define the layout on a per-page basis, so its also called as Per-Page Layouts.
Users.getLayout = function getLayout() {
const [data, setData] = useState(null)
useEffect(() => {
fetch('/api/userdata/user?limit=10',{
headers: {
"content-type": "application/json",
"app-id": " xxxxx",
},
})
.then((res) => res.json())
.then((data) => {
setData(data)
})
}, [])
const sectionData = {
fields:sectionJsonContent
} as unknown as SectionProps;
return (
<NonSitecorePageLayout
title="Integrations | Users"
>
<Section {...sectionData}/>
<div><strong>Use of NextJS Config Rewrites</strong></div>
{ renderUser(data?.data)}
</NonSitecorePageLayout>
);
};
After getting the data from proxy api call, it’s passed to renderUser call to render the user related HTML block.
Now, actual api endpoint wouldn’t be visible to end users:
- Implement API Proxy using Next.js middleware
The
http-proxy-middleware is a
Node.js package that provides a middleware to handle HTTP proxy requests. It is commonly used in web development to proxy requests from a client to a server.
-
To implement API proxy using middleware package http-proxy-middleware you have to first install the package at the route of your rendering code base (where Website\src\rendering\package.json present)
npm install http-proxy-middleware
-
Create a new API proxy middleware file called apiProxy.js (Website\src\rendering\apiProxy.js) in the root directory of your project at Website\src\rendering\
const { createProxyMiddleware } = require('http-proxy-middleware')
module.exports = createProxyMiddleware({
target: 'https://dummyapi.io/data/v1',
changeOrigin: true,
pathRewrite: {
'^/api/proxydata': ''
}
})
In this example, we're creating a proxy middleware that proxies requests to the https://dummyapi.io/data/v1 API. The changeOrigin option is set to true to rewrite the Host header to the target URL.
-
Import the API proxy middleware in your Sitecore Next.js configuration file (usually next.config.js):
async rewrites() {
// When in connected mode we want to proxy Sitecore paths off to Sitecore
return [
// External API > user details
{
source: '/api/proxydata/:path*',
destination: `/apiProxy/:path*`,
},
];
},
async serverMiddleware() {
return [
apiProxy,
]
}
In this example, we're using Next.js rewrites to match any requests to /api/proxydata/* and rewrite them to /apiProxy/*. Then, we're using server middleware to apply the API proxy middleware to all requests matching /apiProxy/*.
-
I have used the proxy endpoint in Sitecore Next.JS application in the Non-Sitecore page at \src\rendering\src\pages\integrations\users\index.tsx. In this file I have used the useEffect to call the middleware proxy api call to fecth data from actual third-party api call https://dummyapi.io/data/v1/ inside the Next.js, getLayout function
Users.getLayout = function getLayout() {
const [httpProxyData, setHttpProxyData] = useState(null)
useEffect(() => {
fetch('/api/proxydata/user?limit=10&page=3',{
headers: {
"content-type": "application/json",
"app-id": " xxxxx",
},
})
.then((res) => res.json())
.then((httpProxyData) => {
setHttpProxyData(httpProxyData)
})
}, [])
const sectionData = {
fields:sectionJsonContent
} as unknown as SectionProps;
return (
<NonSitecorePageLayout
title="Integrations | Users"
>
<Section {...sectionData}/>
<div><strong>Use of Proxy Middleware</strong></div>
{ renderUser(httpProxyData?.data?)}
</NonSitecorePageLayout>
);
};
In this example, we make a request to /api/proxydata/user, which will be proxied to https://dummyapi.io/data/v1 by the API proxy middleware.
- Implement API Proxy using API route
In Next.js, you can create
API routes to handle server-side logic and respond to HTTP requests. API routes in Next.js are files placed in the
/pages/api directory of your project.
Next.js's API routes offer a way to construct your API.
Any file located in the folder
pages/api is mapped to
/api/* and is handled more like an API endpoint than a page. They don't raise the size of your client-side bundle because they are server-side only bundles.
-
To implement API route, create a new folder called proxy inside the /pages/api directory at /pages/api/proxy. In this folder (/pages/api/proxy) create a new file and you can name it whatever you like, but let's use users.js for this example.
-
Open the users.js file and add the following code
import axios from 'axios'
export default async function handler(req, res) {
const response = await axios.get('http://localhost:3000/api/users')
res.status(200).json({
data: response.data,
});
}
Save the file. Next.js automatically maps the file name to the corresponding route. For example, users.js will be accessible at /api/proxy/users.
In the above, we are making call to localhost api end point users which will provide the user’s details.
-
Let’s create another API end point at \pages\api\ which will make a call to actual third party api. For this create folder users inside the \pages\api and then create an index.ts file (\pages\api\users\index.ts) inside the users folder.
-
Add following code inside the index.ts file (\pages\api\users\index.ts)
export default async function handler(req: any, res:any) {
const response= await fetch('https://dummyapi.io/data/v1/user?limit=10&page=2',{
headers: {
"content-type": "application/json",
"app-id": " xxxxx",
},
})
const data = await response.json();
res.status(200).json(data);
}
In this example, we're creating a API endpoint which proxies requests to the https://dummyapi.io/data/v1 API and return the result to API route /api/proxy/users.
-
I have used the API route endpoint in Sitecore Next.JS application in the Non-Sitecore page at \src\rendering\src\pages\integrations\users\index.tsx. In this file I have used the useEffect to call the proxy api end route to fecth data from another api route which make call to actual api https://dummyapi.io/data/v1/ to get the data
Users.getLayout = function getLayout() {
const [proxyData, setProxyData] = useState(null)
useEffect(() => {
fetch('/api/proxy/users',{
headers: {
"content-type": "application/json",
"app-id": "xxxxx",
},
})
.then((res) => res.json())
.then((proxyData) => {
setProxyData(proxyData)
})
}, [])
const sectionData = {
fields:sectionJsonContent
} as unknown as SectionProps;
return (
<NonSitecorePageLayout
title="Integrations | Users"
>
<Section {...sectionData}/>
<div><strong>Use of Proxy Route</strong></div>
{ renderUser(proxyData?.data?.data)}
</NonSitecorePageLayout>
);
};
In this example, we make a request to /api/proxy/users, which will be proxied to https://dummyapi.io/data/v1 by the API /api/users.
By following the above listed options and steps, you can create the proxies for your api calls.
API proxies in Next.js allow developers to easily route incoming requests to external APIs, while also providing a layer of abstraction that can help protect sensitive API keys and credentials. Additionally, API proxies can be used to implement CORS Handling, Server-Side Authorization and Authentication, Rate Limiting and Throttling, Response Manipulation and Caching including Microservices and Backend Integration.
Check out the resource mentioned above as well as this blog if you're curious to learn more about Sitecore JSS and NextJS.
The code base present at the GitHub branch
Comments