Handling Dynamic Routes in API Middleware

Handling Dynamic Routes in API Middleware

Introduction:

Dynamic routes are a powerful feature of Next.js, allowing you to create pages or APIs with parameters like /user/[id]. However, when using middleware to handle requests to dynamic routes, developers often face issues such as incorrect parameter extraction or unintended behavior.

In this blog, we’ll explore one such problem, discuss the root cause, and provide a solution with examples.

Uncaught TypeError: Cannot Read Property ‘X’ of Undefined

The Problem:

Imagine you’re building a user profile page with an API route /api/user/[id]. You add middleware to log user activity and restrict access based on roles. However, you notice that the middleware doesn’t correctly handle dynamic parameters like [id]. For instance:

  1. Parameters are sometimes undefined.
  2. Middleware runs even on routes where it shouldn’t.

import { NextResponse } from ‘next/server’;

export function middleware(req) {
const { pathname } = req.nextUrl;
console.log(‘Pathname:’, pathname); // Expect ‘/api/user/123’

if (pathname.startsWith(‘/api/user’)) {
const userId = pathname.split(‘/’).pop();
console.log(‘User ID:’, userId); // Sometimes returns undefined!
}

return NextResponse.next();
}

When you access /api/user/123, the userId may not resolve correctly, leading to errors.

Understanding the Issue

The issue arises because middleware in Next.js operates on the URL’s pathname, not the resolved dynamic parameters. If you rely on simple string manipulation without validating the route structure, you’ll encounter errors when the path doesn’t exactly match your expectation.

The Solution:

To fix this, use the nextUrl.pathname property and validate it against the dynamic route structure. Here’s an updated version:

import { NextResponse } from ‘next/server’;

export function middleware(req) {
const { pathname } = req.nextUrl;

// Check if the route matches the dynamic structure
const dynamicRoute = /^\/api\/user\/(\d+)$/;
const match = pathname.match(dynamicRoute);

if (match) {
const userId = match[1]; // Extract the dynamic parameter
console.log(‘User ID:’, userId); // Correctly logs ‘123’

// Perform additional checks or actions
if (parseInt(userId) > 1000) {
return new NextResponse(‘User not allowed’, { status: 403 });
}
}

return NextResponse.next();
}

Explanation

  • Regex Validation: The dynamicRoute regex ensures the route matches the expected structure.
  • Parameter Extraction: Using match[1], you extract and validate the dynamic parameter.
  • Conditional Logic: You can now add role-based access checks or logging safely.

Leave a Comment

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

Scroll to Top