Handling CORS in Next.js: Best Practices and Solutions

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]

Handling CORS in Next.js: Best Practices and Solutions

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.

Leave a Comment

Your email address will not be published. Required fields are marked *