Güncelleme notu: Next.js 16 ile birlikte
middleware.tsdosyasıproxy.ts,middlewarefonksiyonu daproxyolarak yeniden adlandırıldı. Aşağıdaki kavramlar (matcher, rewrite, cookie ve header yönetimi) aynı şekilde geçerli.

Middleware Nedir? Ne Zaman Kullanılır?
Kafanda şu an şöyle bir sahne olabilir: "Bir request, tarayıcıdan çıkıp server'a doğru yola çıkmış. Yolda, elinde dijital bir düdük olan middleware abimiz durduruyor: 'Dur bakalım, sen nereye gidiyorsun? Kimlik var mı? Header'ın sağlam mı?'"
Aslında tam olarak bu!
Next.js'te Middleware, bir isteğin tamamlanmasından önce çalışan küçük ama güçlü bir kod bloğudur. Gelen isteğe göre bazı değişiklikler yapabilir:
- Kullanıcıyı başka bir sayfaya yönlendirebilir (redirect),
- Farklı bir sayfaya yönlendirilmiş gibi davranabilir (rewrite),
- Header'lara özel bilgiler ekleyebilir veya silebilir,
- Hatta direkt olarak yanıt dönebilir (response).

En güzel yanı şu: Middleware, sayfa cache'lerinden önce ve route eşleşmeleri yapılmadan hemen önce çalışır. Yani bir sayfa ne kadar önbelleğe alınmış olursa olsun, middleware onu görür. Bu sayede gerçekten hızlı ve hafif işlemler yapılabilir.
Kullanım Senaryoları
👣 Hızlı Yönlendirmeler: Kullanıcıdan gelen isteğin küçük bir kısmını okuyup hemen başka bir sayfaya göndermek (örneğin, dil bazlı yönlendirme).
🧪 A/B Testleri: Kullanıcıyı farklı deneyimlere yönlendirmek.
📦 Header Manipülasyonu: Bütün sayfalara özel header eklemek (örneğin X-Robots-Tag gibi).
🍪 Cookie Manipülasyonu: Kullanıcı siteyi karanlık modda kullanıyorsa, bu tercihini saklamak.
İlk Middleware'inizi Yazın
/my-next-app
├── app/
├── public/
├── middleware.ts
..
Next.js, sadece tek bir middleware.ts (veya .js) dosyasını destekler. Her projede yalnızca bir middleware.ts dosyası desteklense de, middleware'inizi modüler yapabilirsiniz. İşlevleri ayrı .ts veya .js dosyalarına ayırıp middleware.ts içinde birleştirerek merkezi ve sade bir yapı elde edilir. Bu yöntem, çakışmaları önler, yapıyı sadeleştirir ve performansı artırır.
// middleware.ts
import type { NextRequest } from "next/server";
import { authMiddleware } from "./middlewares/auth";
import { experimentRedirect } from "./middlewares/abTesting";
export function middleware(request: NextRequest) {
if (request.nextUrl.pathname.startsWith('/admin')) {
return authMiddleware(request);
}
return experimentRedirect(request);
}
Middleware'in Çalışma Sırası
Middleware, Next.js uygulamasında belirli bir sırayla çalıştırılır; middleware yazarken dönüp bakmamız gereken bir sıralamadır.
next.config.jsiçindekiheadersnext.config.jsiçindekiredirects- …devamını bu linkten inceleyebilirsiniz: matching paths
Bu yapı sayesinde middleware'lerin yalnızca ihtiyaç duyulan yollar üzerinde çalışması sağlanır, performans kayıpları ve karmaşa engellenir.
Matcher ile Yol Belirleme
matcher özelliği ile middleware'in hangi rotalarda çalışacağını belirleyebilirsiniz. Tek bir yol ya da birden fazla yolu dizi şeklinde tanımlayabilirsiniz:
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
return NextResponse.redirect(new URL('/home', request.url))
}
export const config = {
matcher: ['/about/:path*', '/dashboard/:path*'],
}
Daha gelişmiş eşleşmeler için RegEx desteklenmektedir. Örneğin bazı yolları hariç tutmak için "negative lookahead" kullanabilirsiniz:
export const config = {
matcher: [
'/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)',
],
}
has ve missing ile filtreleme
Amaç: Middleware'in sadece gerekli durumlarda devreye girmesini sağlamak.
matcher: [
{
source: '/((?!api|_next|favicon.ico|sitemap.xml|robots.txt).*)',
// Bu header'lar yoksa çalış
missing: [
{ type: 'header', key: 'next-router-prefetch' },
{ type: 'header', key: 'purpose', value: 'prefetch' },
],
},
{
source: '/((?!api|_next|favicon.ico|sitemap.xml|robots.txt).*)',
// Bu header'lar varsa çalış
has: [
{ type: 'header', key: 'next-router-prefetch' },
{ type: 'header', key: 'purpose', value: 'prefetch' },
],
},
{
source: '/((?!api|_next|favicon.ico|sitemap.xml|robots.txt).*)',
// Belirli bir header varsa ama bir diğeri eksikse çalış
has: [{ type: 'header', key: 'x-present' }],
missing: [{ type: 'header', key: 'x-missing', value: 'prefetch' }],
},
]
Conditional Rewrite
Amaç: Gelen isteklere göre yönlendirme yapmaktır. İsteklerin URL'si belirli bir desene göre kontrol edilir ve eşleşen yollar yeni bir URL'ye yönlendirilir. /admin ile başlayan bir URL geldiğinde, kullanıcıyı /internal/admin-panel sayfasına yönlendiriyoruz.
export function middleware(request: NextRequest) {
if (request.nextUrl.pathname.startsWith('/admin')) {
return NextResponse.rewrite(new URL('/internal/admin-panel', request.url))
}
return NextResponse.next()
}
Cookie Management (Çerezlerle Kullanım)
Çerez işlemleri (cookies.get/set/delete) kullanıcı oturumu, tema seçimi gibi durumlarda kullanılır. Aşağıdaki kod bloğu kullanıcıların oturum açıp açmadığını kontrol eder ve buna göre yönlendirme yapar. Eğer auth_token çerezi yoksa, kullanıcıyı /login sayfasına yönlendirir. Ayrıca, kullanıcının en son ziyaret ettiği sayfa last_visited çerezi olarak saklanır.
export function middleware(request: NextRequest) {
const authToken = request.cookies.get('auth_token')
if (!authToken) return NextResponse.redirect(new URL('/login', request.url))
const response = NextResponse.next()
response.cookies.set('last_visited', request.nextUrl.pathname)
return response
}
// ...
request.cookies.get('auth_token') // Belirtilen key adındaki çerezi okur
response.cookies.set('auth_token', '123abc') // Bir çerez oluşturur veya var olan bir çerezi günceller
request.cookies.delete('auth_token') // Belirtilen key adındaki çerezi siler
Setting Request/Response Headers (İstek manipülasyonu)
API'yi kullanarak istek ve yanıt başlıklarını ayarlayabiliriz:
export function middleware(request: NextRequest) {
// Gelen isteğin başlıklarını al ve üzerinde değişiklik yap
const requestHeaders = new Headers(request.headers)
// Yeni bir başlık ekle: İstemciden gelen istek türünü belirtmek için
requestHeaders.set('x-client-type', 'internal-service')
// Yeni başlıklarla bir yanıt oluştur ve isteği ilet
const response = NextResponse.next({
request: {
headers: requestHeaders, // Yeni başlıkları ilet
},
})
// Yanıt başlıklarına yeni bir başlık ekle: Middleware'in çalıştığını belirtmek için
response.headers.set('x-middleware-trace', 'enabled')
return response
}
Middleware'den Özel Yanıtlar
Bu yöntemle, istekle ilgili hata durumlarını kolayca yönetebilir ve kullanıcıyı yönlendirebiliriz.
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { isAuthenticated } from '@lib/auth'
export const config = {
matcher: '/api/:function*',
}
export function middleware(request: NextRequest) {
if (!isAuthenticated(request)) {
// Kimlik doğrulama başarısızsa, 401 ile hata mesajı içeren JSON yanıtı döndür
return Response.json(
{ success: false, message: 'authentication failed' },
{ status: 401 }
)
}
return NextResponse.next()
}
⚙️ Kısa Notlar
- CORS Yönetimi: Middleware kullanarak Cross-Origin Resource Sharing (CORS) başlıklarını ayarlayabilirsiniz. Bu, dış kaynaklardan gelen istekleri kontrol etmek için kullanılır. Özellikle preflight (OPTIONS) istekleri ve basit istekler için CORS başlıklarını yönetebilirsiniz. CORS başlıkları, güvenli ve kontrollü API erişimi sağlamak için kritik öneme sahiptir.
- waitUntil ve NextFetchEvent:
waitUntil()metodu, asenkron işlemleri bekleterek middleware'in arka planda çalışmasına olanak tanır. - Advanced Middleware Flags:
// next.config.js
module.exports = {
// Eğik çizgi (trailing slash) yönlendirmelerini devre dışı bırakır
skipTrailingSlashRedirect: true,
// URL normalleştirmesini devre dışı bırakır, orijinal URL'yi kullanır
skipMiddlewareUrlNormalize: true,
}
// Bir URL'nin sonuna eğik çizgi eklenmesini kontrol eden kod
if (
!pathname.endsWith('/') &&
!pathname.match(/((?!\.well-known(?:\/.*)?)(?:[^/]+\/)*[^/]+\.\w+)/)
) {
return NextResponse.redirect(
new URL(`${req.nextUrl.pathname}/`, req.nextUrl)
)
}
- Unit Testing (Deneysel): Next.js v15.1 ile middleware için unit test yazılabilir; middleware'in yalnızca belirli yollar için çalışıp çalışmadığını test edebilirsiniz.
- Edge vs. Node.js Runtime: Edge runtime daha hızlıdır, ancak Node.js runtime daha fazla esneklik sunar (deneysel).
🚀 Sonuç
Next.js'te Middleware, istekleri işleyerek yönlendirme, kimlik doğrulama, header ve cookie yönetimi gibi görevleri merkezi bir noktada gerçekleştirir. Middleware'i etkili bir şekilde nasıl kullanacağınızı anlamak, projenizin içine ve dışına giden veri akışını önemli ölçüde iyileştirebilir. Bu sayede, geliştiriciler için güçlü ve esnek bir araç haline gelir.
Ben bu süreçte öğrenirken keyif aldım, umarım size bu bilgileri aktarmamın faydasını görürsünüz.
Keyifli kodlamalar 👨💻 🎉
Bu yazı ilk olarak Medium'da yayınlandı.