Next.js middleware matcher negate path
Asked Answered
H

3

8

I have a middleware on a Next.js project, and I want to negate my /api/* route.

In other words, I want middleware to run for every route except anything that starts with /api/. I couldn't find an example in the docs.

How do I achieve that (of course, without writing all included routes one by one)?

Henriquez answered 19/8, 2022 at 10:41 Comment(0)
S
9

You cannot do this with matcher, because it only accepts simple path patterns, therefore you'll need to use conditional statement:

export function middleware(request: NextRequest) {
 if (request.nextUrl.pathname.startsWith('/api/')) {
   return NextResponse.next()
 }

 // your middleware logic
}
Spend answered 19/8, 2022 at 11:28 Comment(2)
While I personally would prefer a declarative/config level approach instead of imperative coding, I think this is the way to go in this situation, it works perfectly!Sapsago
There is one catch with this approach: your middleware will be invoked for every request, whereas if you use the matcher it will only invoke when there is a match. Keep in mind that you will most likely be billed for middleware invocations on your hosting platform.Shortlived
P
13

Looks like the middleware docs have been updated to account for something like this.

nextjs middleware docs

export const config = {
  matcher: [
    /*
     * Match all request paths except for the ones starting with:
     * - api (API routes)
     * - static (static files)
     * - favicon.ico (favicon file)
     */
    '/((?!api|static|favicon.ico).*)',
  ],
}
Poetize answered 15/10, 2022 at 9:5 Comment(0)
S
9

You cannot do this with matcher, because it only accepts simple path patterns, therefore you'll need to use conditional statement:

export function middleware(request: NextRequest) {
 if (request.nextUrl.pathname.startsWith('/api/')) {
   return NextResponse.next()
 }

 // your middleware logic
}
Spend answered 19/8, 2022 at 11:28 Comment(2)
While I personally would prefer a declarative/config level approach instead of imperative coding, I think this is the way to go in this situation, it works perfectly!Sapsago
There is one catch with this approach: your middleware will be invoked for every request, whereas if you use the matcher it will only invoke when there is a match. Keep in mind that you will most likely be billed for middleware invocations on your hosting platform.Shortlived
T
0

It might help

const matcherRegex = new RegExp('^(?!/(?:_next/static|favicon\\.ico|swc\\.js|api)(?:/|$))');

export function middleware(request: NextRequest){
  const isMiddlewareAllowed = matcherRegex.test(pathname)

  if (isMiddlewareAllowed) {
  //...
  }else return
}
Talcahuano answered 10/6, 2023 at 22:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.