Cross-origin resource sharing or CORS is a critical security feature provided by web browsers that prevent from making requests to other domain that are not the same as the current one from which the web pages is served.
CORS is a very important feature in terms of the security of the application. But sometimes it becomes challenging for developers to correctly and efficiently implement it. In this article, we will discuss the best ways to implement and handle CORS in Next js with examples.
[lwptoc]
Understanding CORS
When a web application makes a request to a resource on a different domain, the browser verifies if the server on the other side allows this request or not. If the request is not allowed via appropriate CORS headers, the browser will throw the CORS issue and block the request.
Using this security measure, browsers prevent malicious websites from making unauthorized requests to other domains.
In a Next js application, we might face CORS issues when:
- Making API requests to a different domain.
- Serving assets like fonts, images or JSON configuration files from another domain.
- Implementing server-side rendering (SSR) to fetch data from external APIs.
Best Practices to Handle CORS in Next js App
Now we will discuss various approaches to handle CORS in the Next js application with practicable examples:
1. Use Middleware for CORS Handling
Using middleware is one of the most common ways to handle CORS in the Next JS application. The cors middleware package is a popular choice for setting up CORS easily as shown below:
// pages/api/my-api.js
// Import required modules
import Cors from 'cors';
import { runMiddleware } from '../../utils/api';
// Initialize CORS middleware with custom options
const corsOptions = {
origin: 'https://example.com', // Replace with your allowed origin
methods: ['GET', 'POST', 'PUT', 'DELETE'], // Define the HTTP methods allowed
optionsSuccessStatus: 204, // Sets the status code for successful CORS preflight requests to 204
};
// Create a CORS middleware instance
const corsMiddleware = Cors(corsOptions);
// Define your API route handler
export default async function handler(req, res) {
try {
// Run the CORS middleware to handle CORS headers
await runMiddleware(req, res, corsMiddleware);
// Your API logic here
if (req.method === 'GET') {
// Handle GET request logic
res.json({ message: 'GET request handled successfully' });
} else if (req.method === 'POST') {
// Handle POST request logic
res.json({ message: 'POST request handled successfully' });
} else if (req.method === 'PUT') {
// Handle PUT request logic
res.json({ message: 'PUT request handled successfully' });
} else if (req.method === 'DELETE') {
// Handle DELETE request logic
res.json({ message: 'DELETE request handled successfully' });
} else {
// Handle unsupported HTTP methods
res.status(405).json({ error: 'Method not allowed' });
}
} catch (error) {
console.error('Error:', error);
res.status(500).json({ error: 'Internal server error' });
}
}
In the above example, we can define the allowed origin in place of https://example.com inside thecorsOptions
, the allowed HTTP methods, and the success status code for CORS preflight requests.
Thereafter, we created the CORS middleware instance corsMiddleware
by passing corsOptions
as an argument to Cors(corsOptions)
.
The API handler will check the request method type and respond with a message accordingly. Also, we have an error handling to catch any unexpected errors and respond with an internal server error (status code 500) if some error.
2. Handling CORS in a Global Middleware
Let’s see how you can apply CORS handling globally for all the API routes, by creating a custom middleware:
// utils/cors.js
import Cors from 'cors';
// Initialize CORS middleware
const cors = Cors({
origin: 'https://example.com', // Replace with your allowed origin
methods: ['GET', 'POST', 'PUT', 'DELETE'],
});
export default function handleCors(req, res) {
return new Promise((resolve, reject) => {
cors(req, res, (result) => {
if (result instanceof Error) {
return reject(result);
}
return resolve(result);
});
});
}
After creating the global middleware, we can use this middleware in our API routes as shown below:
// pages/api/my-api.js
import { handleCors } from '../../utils/cors';
export default async function handler(req, res) {
await handleCors(req, res);
// Your API logic here
res.json({ message: 'Hello from my API' });
}
This way by creating a global middleware, we can maintain consistency for all the API routes at one place.
3. Setting CORS Headers on the server
Now, we will see, how to set the CORS headers on the server to allow cross-origin requests by using the middleware or by configuring the Next js server directly.
Setting CORS headers using middleware:
Create a new file named cors.js in your pages/api directory:
// pages/api/cors.js
import Cors from 'cors';
// Initialize CORS middleware
const cors = Cors({
methods: ['GET', 'POST'],
});
const handler = (req, res) => {
// Apply CORS middleware to handle the CORS headers
return new Promise((resolve, reject) => {
cors(req, res, (result) => {
if (result instanceof Error) {
return reject(result);
}
// Continue processing the request here
res.setHeader('Content-Type', 'application/json');
res.statusCode = 200;
res.end(JSON.stringify({ message: 'CORS-enabled API response' }));
return resolve(result);
});
});
};
export default handler;
Configuring the Next.js Server Directly:
We can also configure CORS headers directly on the Next js server. This approach will allow us to have elegant control of CORS settings for different routes.
In your pages/api directory, create a file named cors-server.js:
// pages/api/cors-server.js
export default (req, res) => {
// Set CORS headers
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET,POST');
// Continue processing the request here
res.setHeader('Content-Type', 'application/json');
res.statusCode = 200;
res.end(JSON.stringify({ message: 'CORS-enabled API response' }));
};
4. Setting Up a Proxy Server in Next.js
If we are unable to set CORS headers on the server, we can use a proxy that will make requests on behalf of our application. This approach involves setting up a server, that will act as an intermediary between the application and external API.
This proxy server can be configured to add the required headers and forward the request to API externally. For this, we will use the http-proxy-middleware
library. You can install it using npm:
npm install http-proxy-middleware
Thereafter, we will create the proxy.js file as shown below:
// pages/api/proxy.js
import { createProxyMiddleware } from 'http-proxy-middleware'
const proxy = createProxyMiddleware({
target: 'https://api.example.com',
changeOrigin: true,
pathRewrite: {
'^/api/proxy': '/',
},
})
export default proxy
Use the proxy in your API routes we created above as shown below:
// pages/api/data.js
export default async (req, res) => {
await fetch('/api/proxy/data')
.then(response => response.json())
.then(data => {
res.status(200).json(data);
});
}
Now, when a request is made to /api/data, it will proxy the request to https://api.example.com/data using the proxy handler.
Conclusion
We can successfully integrate CORS in the Next js application via various approaches including the use of cors
a package and setting up a proxy by using the http-proxy-middleware
. We discussed how to set up middleware globally, setting up headers and adding configurations as well.
Adding CORS on the server side to set the header by using the middleware or directly on the server we also discussed. In the last section, we discussed how to set a proxy handler http-proxy-middleware
to configure the proxy to access external APIs.
Hope these detailed examples will help you to develop more detailed features in your next js application.