Middleware

Ara yazılım, bir istek tamamlanmadan önce kod çalıştırmanıza olanak tanır. Ardından, gelen isteğe bağlı olarak, yeniden yazarak, yeniden yönlendirerek, istek veya yanıt başlıklarını değiştirerek veya doğrudan yanıt vererek yanıtı değiştirebilirsiniz.

Ara yazılım, önbelleğe alınan içerik ve yollar eşleştirilmeden önce çalışır. Daha fazla ayrıntı için Yolları Eşleştirme bölümüne bakın.

Convention

Orta Yazılımı tanımlamak için projenizin kök dizinindeki middleware.ts (veya .js) dosyasını kullanın. Örneğin, pages veya app ile aynı seviyede veya varsa src içinde.

Example

middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
 
// This function can be marked `async` if using `await` inside
export function middleware(request: NextRequest) {
  return NextResponse.redirect(new URL('/home', request.url))
}
 
// See "Matching Paths" below to learn more
export const config = {
  matcher: '/about/:path*',
}

Matching Paths

Ara yazılım, projenizdeki her rota için çağrılacaktır. Yürütme sırası aşağıdaki gibidir:

  1. headers itibaren next.config.js
  2. redirects itibaren next.config.js
  3. Ara yazılım (rewrites, redirects, vb.)
  4. beforeFiles (rewrites) adresinden next.config.js
  5. Dosya sistemi rotaları (public/, _next/static/, pages/, app/, vb.)
  6. afterFiles (rewrites) adresinden next.config.js
  7. Dinamik Rotalar (/blog/[slug])
  8. fallback (rewrites) adresinden next.config.js

Middleware'in hangi yollarda çalışacağını tanımlamanın iki yolu vardır:

  1. Özel eşleştirici yapılandırması
  2. Koşullu ifadeler

Matcher

matcher Orta Yazılımı belirli yollarda çalışacak şekilde filtrelemenizi sağlar.

middleware.js
export const config = {
  matcher: '/about/:path*',
}

Bir dizi sözdizimiyle tek bir yolu veya birden fazla yolu eşleştirebilirsiniz:

middleware.js
export const config = {
  matcher: ['/about/:path*', '/dashboard/:path*'],
}

matcher yapılandırması tam regex'e izin verir, böylece negatif lookahead'ler veya karakter eşleştirme gibi eşleştirme desteklenir. Belirli yollar hariç tümünü eşleştirmek için negatif lookahead örneği burada görülebilir:

middleware.js
export const config = {
  matcher: [
    /*
     * Match all request paths except for the ones starting with:
     * - api (API routes)
     * - _next/static (static files)
     * - _next/image (image optimization files)
     * - favicon.ico (favicon file)
     */
    '/((?!api|_next/static|_next/image|favicon.ico).*)',
  ],
}

Ayrıca missing dizisini kullanarak Orta Katmandan geçmesi gerekmeyen prefetch'leri ( next/link adresinden) yok sayabilirsiniz:

middleware.js
export const config = {
  matcher: [
    /*
     * Match all request paths except for the ones starting with:
     * - api (API routes)
     * - _next/static (static files)
     * - _next/image (image optimization files)
     * - favicon.ico (favicon file)
     */
    {
      source: '/((?!api|_next/static|_next/image|favicon.ico).*)',
      missing: [
        { type: 'header', key: 'next-router-prefetch' },
        { type: 'header', key: 'purpose', value: 'prefetch' },
      ],
    },
  ],
}

Bilmekte fayda var: matcher değerlerinin sabit olması gerekir, böylece derleme zamanında statik olarak analiz edilebilirler. Değişkenler gibi dinamik değerler göz ardı edilecektir.

Yapılandırılmış eşleştiriciler:

  1. ile başlamalıdır /
  2. Adlandırılmış parametreler içerebilir: /about/:path, /about/a ve /about/b ile eşleşir ancak /about/a/c
  3. Adlandırılmış parametreler üzerinde değiştiriciler olabilir ( : ile başlayarak): /about/:path*, /about/a/b/c ile eşleşir çünkü * sıfır veya daha fazladır. ? sıfır veya bir ve + bir veya daha fazladır
  4. Parantez içine alınmış düzenli ifade kullanabilir: /about/(.*) ile aynıdır /about/:path*

Path-to-regexp belgeleri hakkında daha fazla bilgi edinin.

Bilmekte fayda var: Geriye dönük uyumluluk için Next.js, /public adresini her zaman /public/index olarak kabul eder. Bu nedenle, /public/:path eşleştiricisi eşleşecektir.

Conditional Statements

middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
 
export function middleware(request: NextRequest) {
  if (request.nextUrl.pathname.startsWith('/about')) {
    return NextResponse.rewrite(new URL('/about-2', request.url))
  }
 
  if (request.nextUrl.pathname.startsWith('/dashboard')) {
    return NextResponse.rewrite(new URL('/dashboard/user', request.url))
  }
}

NextResponse

NextResponse API şunları yapmanızı sağlar:

Middleware'den bir yanıt üretmek için şunları yapabilirsiniz:

  1. rewrite yanıt üreten bir rotaya(Sayfa veya Rota İşleyicisi)
  2. doğrudan bir NextResponse döndürür. Yanıt Üretme bölümüne bakın

Using Cookies

Çerezler normal başlıklardır. Bir Request adresinde Cookie başlığında saklanırlar. Bir Response adresinde Set-Cookie başlığında bulunurlar. Next.js, NextRequest ve NextResponse üzerindeki cookies uzantısı aracılığıyla bu çerezlere erişmek ve bunları değiştirmek için uygun bir yol sağlar.

  1. Gelen istekler için cookies aşağıdaki yöntemlerle birlikte gelir: get, getAll, set ve delete çerezleri. has ile bir çerezin varlığını kontrol edebilir veya clear ile tüm çerezleri kaldırabilirsiniz.
  2. Giden yanıtlar için cookies aşağıdaki yöntemlere sahiptir: get, getAll, set, ve delete.
middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
 
export function middleware(request: NextRequest) {
  // Assume a "Cookie:nextjs=fast" header to be present on the incoming request
  // Getting cookies from the request using the `RequestCookies` API
  let cookie = request.cookies.get('nextjs')
  console.log(cookie) // => { name: 'nextjs', value: 'fast', Path: '/' }
  const allCookies = request.cookies.getAll()
  console.log(allCookies) // => [{ name: 'nextjs', value: 'fast' }]
 
  request.cookies.has('nextjs') // => true
  request.cookies.delete('nextjs')
  request.cookies.has('nextjs') // => false
 
  // Setting cookies on the response using the `ResponseCookies` API
  const response = NextResponse.next()
  response.cookies.set('vercel', 'fast')
  response.cookies.set({
    name: 'vercel',
    value: 'fast',
    path: '/',
  })
  cookie = response.cookies.get('vercel')
  console.log(cookie) // => { name: 'vercel', value: 'fast', Path: '/' }
  // The outgoing response will have a `Set-Cookie:vercel=fast;path=/` header.
 
  return response
}

Setting Headers

NextResponse API'sini kullanarak istek ve yanıt başlıklarını ayarlayabilirsiniz ( istek başlıklarının ayarlanması Next.js v13.0.0'dan beri mevcuttur).

middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
 
export function middleware(request: NextRequest) {
  // Clone the request headers and set a new header `x-hello-from-middleware1`
  const requestHeaders = new Headers(request.headers)
  requestHeaders.set('x-hello-from-middleware1', 'hello')
 
  // You can also set request headers in NextResponse.rewrite
  const response = NextResponse.next({
    request: {
      // New request headers
      headers: requestHeaders,
    },
  })
 
  // Set a new response header `x-hello-from-middleware2`
  response.headers.set('x-hello-from-middleware2', 'hello')
  return response
}

Bilmekte fayda var: Arka uç web sunucusu yapılandırmanıza bağlı olarak 431 Request Header Fields Too Large hatasına neden olabileceğinden büyük başlıklar ayarlamaktan kaçının.

Producing a Response

Middleware'den doğrudan bir Response veya NextResponse örneği döndürerek yanıt verebilirsiniz. (Bu Next.js v13.1.0'dan beri mevcuttur )

middleware.ts
import { NextRequest } from 'next/server'
import { isAuthenticated } from '@lib/auth'
 
// Limit the middleware to paths starting with `/api/`
export const config = {
  matcher: '/api/:function*',
}
 
export function middleware(request: NextRequest) {
  // Call our authentication function to check the request
  if (!isAuthenticated(request)) {
    // Respond with JSON indicating an error message
    return Response.json(
      { success: false, message: 'authentication failed' },
      { status: 401 }
    )
  }
}

waitUntil and NextFetchEvent

NextFetchEvent nesnesi, yerel FetchEvent nesnesini içerir ve waitUntil() yöntem.

waitUntil() yöntemi argüman olarak bir söz alır ve söz yerine gelene kadar Orta Yazılımın ömrünü uzatır. Bu, arka planda iş yapmak için kullanışlıdır.

middleware.ts
import { NextResponse } from 'next/server'
import type { NextFetchEvent, NextRequest } from 'next/server'
 
export function middleware(req: NextRequest, event: NextFetchEvent) {
  event.waitUntil(
    fetch('https://my-analytics-platform.com', {
      method: 'POST',
      body: JSON.stringify({ pathname: req.nextUrl.pathname }),
    })
  )
 
  return NextResponse.next()
}

Advanced Middleware Flags

Next.js'nin v13.1 adresinde, gelişmiş kullanım durumlarını ele almak için ara yazılım, skipMiddlewareUrlNormalize ve skipTrailingSlashRedirect için iki ek bayrak tanıtıldı.

skipTrailingSlashRedirect sondaki eğik çizgileri eklemek veya kaldırmak için Next.js yönlendirmelerini devre dışı bırakır. Bu, bazı yollar için sondaki eğik çizgiyi korumak için ara yazılım içinde özel işleme izin verir, ancak diğerleri için değil, bu da artımlı geçişleri kolaylaştırabilir.

next.config.js
module.exports = {
  skipTrailingSlashRedirect: true,
}
middleware.js
const legacyPrefixes = ['/docs', '/blog']
 
export default async function middleware(req) {
  const { pathname } = req.nextUrl
 
  if (legacyPrefixes.some((prefix) => pathname.startsWith(prefix))) {
    return NextResponse.next()
  }
 
  // apply trailing slash handling
  if (
    !pathname.endsWith('/') &&
    !pathname.match(/((?!\.well-known(?:\/.*)?)(?:[^/]+\/)*[^/]+\.\w+)/)
  ) {
    req.nextUrl.pathname += '/'
    return NextResponse.redirect(req.nextUrl)
  }
}

skipMiddlewareUrlNormalize doğrudan ziyaretlerin ve istemci geçişlerinin aynı şekilde ele alınmasını sağlamak için Next.js'deki URL normalleştirmesinin devre dışı bırakılmasına olanak tanır. Bazı gelişmiş durumlarda, bu seçenek orijinal URL'yi kullanarak tam kontrol sağlar.

next.config.js
module.exports = {
  skipMiddlewareUrlNormalize: true,
}
middleware.js
export default async function middleware(req) {
  const { pathname } = req.nextUrl
 
  // GET /_next/data/build-id/hello.json
 
  console.log(pathname)
  // with the flag this now /_next/data/build-id/hello.json
  // without the flag this would be normalized to /hello
}

Runtime

Middleware şu anda yalnızca Edge çalışma zamanını desteklemektedir. Node.js çalışma zamanı kullanılamaz.

Version History

Version Changes
v13.1.0 Advanced Middleware flags added
v13.0.0 Middleware can modify request headers, response headers, and send responses
v12.2.0 Middleware is stable, please see the upgrade guide
v12.0.9 Enforce absolute URLs in Edge Runtime (PR )
v12.0.0 Middleware (Beta) added