next.jsjwtmiddlewareapp-router

Create middleware which rewrites headers and redirects url to API server


I'm attempting to make a middleware for making API calls to a separate server but failing to make a redirect/rewrite. Paths which starts with /api/proxy should be written without that prefix and route to the API server. I'm using NextJS v.15.1.4, NextAuth 5.0.0-beta.25 and @rescale/nemo 1.4 for combining (future) middlewares.

My middleware.ts looks like this at the moment:

import { NextResponse } from "next/server";
import { cookies } from 'next/headers';
import { createMiddleware, type MiddlewareFunctionProps } from '@rescale/nemo'
import { auth } from 'auth';

const globalMiddlewares = {
  before: async ({ request }: MiddlewareFunctionProps) => {
    if (!request.url.includes("api/auth")) {
      return;
    }
    auth()
  },
};

const middlewares = {
  "/api/proxy/*segments": [
    async ({ request, response, context, event, forward, params }: MiddlewareFunctionProps) => {

      const sessionCookieName = process.env.NODE_ENV === "development"
        ? "authjs.session-token"
        : "__Secure-next-auth.session-token";
      const cookieStore = await cookies();
      const bearerToken = cookieStore.get(sessionCookieName);

      request.headers.set("Authorization", "Bearer " + bearerToken?.value);

      const newHeaders = new Headers(request.headers);
      newHeaders.set("Authorization", "Bearer " + bearerToken?.value);

      const newResponse = NextResponse.next({
        request: {
          headers: newHeaders
        }
      });

      forward(newResponse);

    },
    async ({ request, response, context, event, forward, params }: MiddlewareFunctionProps) => {

      const path = params()?.segments?.join("/");

      return NextResponse.rewrite(new URL(path, process.env.NEXT_PUBLIC_API_BASE));

    }
  ]
}

// create middleware
export const middleware = createMiddleware(middlewares, globalMiddlewares);

export const config = {
  matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"],
}
```

Solution

  • It seems like it's not possible to redirect or fetch data from an external server in combination with modified headers any longer according to: https://nextjs.org/docs/messages/middleware-upgrade-guide#edge-api-routes

    The solution would be to intercept calls with a route handler. In this case :

    // /app/api/proxy/[...all]/route.ts
    
    import { NextResponse } from "next/server";
    import { type NextRequest } from 'next/server'
    // From https://nextjs.org/docs/messages/middleware-upgrade-guide#edge-api-routes
    
    export const config = {
      runtime: 'edge',
    }
    
    export async function GET(request: NextRequest) {
    
      const sessionCookieName = process.env.NODE_ENV === "development"
        ? "authjs.session-token"
        : "__Secure-next-auth.session-token";
      const bearerToken = request.cookies.get(sessionCookieName);
      if (!bearerToken) {
        // TODO: return error.
        return NextResponse.next();
      }
    
      const url = new URL(request.url);
      const targetPath = url.pathname.replace("/api/proxy/", "");
      const targetURL = new URL(targetPath, process.env.NEXT_PUBLIC_API_BASE)
    
      const response = await fetch(targetURL.href, {
        method: request.method,
        headers: {
          "Authorization": `Bearer ${bearerToken.value}`,
        },
        redirect: 'manual',
      })
      return response;
    }
    
    // TODO: Add other request handlers