NextJs
API Routes

API Routes in Next.js

API Routes in Next.js allow you to build your API endpoints directly within your application without needing a separate server. This integration can simplify your application architecture and development workflow by keeping both frontend and backend logic in one place. Here’s an in-depth look at various aspects of API routes in Next.js:


1. API Routes: Creating RESTful APIs

In Next.js, API routes are created by adding JavaScript or TypeScript files to the pages/api directory. Each file corresponds to an API endpoint. These routes can be used to handle HTTP requests and perform operations such as fetching data from a database, processing form submissions, or handling authentication.

Example: Basic API Route

// pages/api/hello.js
export default function handler(req, res) {
  res.status(200).json({ message: 'Hello World' });
}
  • File: pages/api/hello.js
  • Endpoint: /api/hello
  • Response: { message: 'Hello World' }

In this example, a GET request to /api/hello will return a JSON response with a simple message.

Handling Different HTTP Methods

You can handle different HTTP methods (GET, POST, PUT, DELETE) by checking req.method in your API route handler.

// pages/api/posts.js
export default function handler(req, res) {
  switch (req.method) {
    case 'GET':
      res.status(200).json({ posts: [] }); // Fetch and return posts
      break;
    case 'POST':
      // Handle creating a new post
      res.status(201).json({ message: 'Post created' });
      break;
    default:
      res.setHeader('Allow', ['GET', 'POST']);
      res.status(405).end(`Method ${req.method} Not Allowed`);
  }
}

Here:

  • GET requests return a list of posts.
  • POST requests simulate the creation of a new post.
  • Unsupported methods return a 405 Method Not Allowed status.

2. Dynamic API Routes

Dynamic API routes are useful when you need to handle requests with varying parameters. You can create dynamic routes by using file names with brackets in the pages/api directory.

Example: Dynamic API Route

// pages/api/posts/[id].js
export default async function handler(req, res) {
  const { id } = req.query; // Get dynamic parameter from URL
  
  if (req.method === 'GET') {
    // Fetch post by ID from the database
    const post = { id, title: 'Sample Post' }; // Example data
    res.status(200).json(post);
  } else {
    res.setHeader('Allow', ['GET']);
    res.status(405).end(`Method ${req.method} Not Allowed`);
  }
}
  • File: pages/api/posts/[id].js
  • Endpoint: /api/posts/123 (where 123 is the dynamic ID)
  • Response: { id: '123', title: 'Sample Post' }

Here, req.query.id retrieves the dynamic parameter from the URL.


3. Middleware

Middleware functions in Next.js API routes allow you to run custom code before a request is completed. This can be used for tasks such as authentication, logging, or validation.

Example: Authentication Middleware

// lib/authMiddleware.js
export function authenticate(req, res, next) {
  // Example authentication logic
  if (req.headers.authorization === 'Bearer my-secret-token') {
    next(); // Proceed to the handler
  } else {
    res.status(401).json({ message: 'Unauthorized' });
  }
}

Using Middleware in an API Route

// pages/api/protected.js
import { authenticate } from '../../lib/authMiddleware';
 
export default function handler(req, res) {
  authenticate(req, res, () => {
    res.status(200).json({ message: 'Protected data' });
  });
}

In this example:

  • The authenticate middleware checks if the request contains a valid authorization token before proceeding to the main handler.

4. Rate Limiting in API Routes

Rate limiting helps to prevent abuse of your API by limiting the number of requests a user can make in a given time period. This can be implemented using libraries like express-rate-limit or by writing custom logic.

Example: Simple Rate Limiting

// lib/rateLimit.js
import rateLimit from 'express-rate-limit';
 
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100, // Limit each IP to 100 requests per windowMs
  message: 'Too many requests, please try again later.',
});
 
export default limiter;

Using Rate Limiting in an API Route

// pages/api/limited.js
import rateLimit from '../../lib/rateLimit';
 
export default async function handler(req, res) {
  // Apply rate limiter middleware
  await rateLimit(req, res, () => {
    res.status(200).json({ message: 'Request successful' });
  });
}

In this example:

  • The rate limiter allows up to 100 requests per IP address every 15 minutes.
  • Requests exceeding this limit receive a 429 Too Many Requests status.

5. Error Handling in API Routes

Proper error handling ensures that your API provides meaningful responses even when something goes wrong. Use try/catch blocks to handle errors and send appropriate HTTP responses.

Example: Error Handling

// pages/api/errorExample.js
export default async function handler(req, res) {
  try {
    // Simulate a potential error
    if (!req.body.data) {
      throw new Error('Missing data');
    }
    
    // Process request and respond
    res.status(200).json({ message: 'Success' });
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
}

In this example:

  • If the request body does not contain data, an error is thrown.
  • The error is caught, and a 400 Bad Request response with the error message is sent.

6. CORS in API Routes

Cross-Origin Resource Sharing (CORS) allows servers to specify who can access resources from different origins. In Next.js API routes, you need to handle CORS to allow requests from other domains.

Example: Enabling CORS

// lib/cors.js
import Cors from 'cors';
 
const cors = Cors({
  methods: ['GET', 'POST', 'OPTIONS'],
  origin: 'https://example.com', // Replace with your allowed origin
});
 
export default function runCors(req, res, next) {
  cors(req, res, next);
}

Using CORS in an API Route

// pages/api/corsExample.js
import runCors from '../../lib/cors';
 
export default function handler(req, res) {
  runCors(req, res, () => {
    res.status(200).json({ message: 'CORS is enabled' });
  });
}

In this example:

  • runCors middleware configures the CORS settings, allowing requests only from https://example.com.