Next.js
مسیریاب app
برنامه تان را بسیازید
مسیریابی Routing
هندلر های مسیر

هندلرهای مسیر

هندلرهای مسیر به شما امکان می دهند با استفاده از API های وب Request (opens in a new tab) و Response (opens in a new tab) درخواست های سفارشی برای یک مسیر خاص ایجاد کنید.


فایل ویژه Route.jsفایل ویژه Route.js

خوب است بدانید: هندلرهای مسیر فقط داخل پوشه app در دسترس هستند. آن ها معادل API Routes ها در پوشه pages هستند، به این معنی که نیازی به استفاده همزمان از API Route و Route Handler نیست.

قرارداد

هندلرهای مسیر در یک فایل route.js|ts داخل پوشه app تعریف می شوند.

app/api/route.ts
export const dynamic = 'force-dynamic' // defaults to auto
export async function GET(request: Request) {}

هندلرهای مسیر را می توان مشابه page.js و layout.js داخل پوشه app تودرتو کرد. اما نمی تواند یک فایل route.js در همان سطح segment مسیر به عنوان page.js وجود داشته باشد.

متدهای HTTP پشتیبانی شده

روش های HTTP methods (opens in a new tab) GET، POST، PUT، PATCH، DELETE، HEAD و OPTIONS پشتیبانی می شوند. اگر از روشی که پشتیبانی نمی شود استفاده شود، Next.js پاسخی با کد ۴۰۵ (Method Not Allowed) برمی گرداند.

API های توسعه یافته NextRequest و NextResponse

Next.js علاوه بر پشتیبانی از Request (opens in a new tab) و Response (opens in a new tab) معمولی، آنها را با NextRequest و NextResponse گسترش می دهد تا برای موارد استفاده پیشرفته، ابزارهای کمکی مناسبی ارائه دهد.

رفتار

کش کردن

هندلرهای مسیر به طور پیش فرض هنگام استفاده از روش GET با شی Response کش می شوند.

app/items/route.ts
export async function GET() {
	const res = await fetch('https://data.mongodb-api.com/...', {
		headers: {
			'Content-Type': 'application/json',
			'API-Key': process.env.DATA_API_KEY,
		},
	})
	const data = await res.json()
 
	return Response.json({ data })
}

هشدار تایپ اسکریپت: Response.json() فقط از TypeScript 5.2 معتبر است. اگر از نسخه پایین‌تر TypeScript استفاده می‌کنید، می‌توانید به جای آن از NextResponse.json() برای پاسخ‌های دارای نوع استفاده کنید.

خارج شدن از کش

می توانید با موارد زیر از کش اجتناب کنید:

  • استفاده از شیء Request با روش GET.
  • استفاده از هر یک از روش های HTTP دیگر (غیر از GET).
  • استفاده از توابع داینامیک مانند cookies و headers.
  • گزینه های پیکربندی بخش Segment Config Options به صورت دستی حالت داینامیک را مشخص می کند.

برای مثال :

app/products/api/route.ts
export async function GET(request: Request) {
	const { searchParams } = new URL(request.url)
	const id = searchParams.get('id')
	const res = await fetch(`https://data.mongodb-api.com/product/${id}`, {
		headers: {
			'Content-Type': 'application/json',
			'API-Key': process.env.DATA_API_KEY!,
		},
	})
	const product = await res.json()
 
	return Response.json({ product })
}

همانطور که مشاهده کردید، متد POST نیز باعث ارزیابی داینامیکی هندلر مسیر می‌شود.

app/items/route.ts
export async function POST() {
	const res = await fetch('https://data.mongodb-api.com/...', {
		method: 'POST',
		headers: {
			'Content-Type': 'application/json',
			'API-Key': process.env.DATA_API_KEY!,
		},
		body: JSON.stringify({ time: new Date().toISOString() }),
	})
 
	const data = await res.json()
 
	return Response.json(data)
}

خوب است بدانید: شبیه Route API ها، هندلرهای مسیر را می‌توان برای مواردی مانند مدیریت ارسال فرم استفاده کرد. در حال حاضر روی یک انتزاع جدید برای هندل کردن فرم‌ها و جهش‌ها که با React یکپارچه می‌شود، کار می‌شود.

شناسایی مسیر

می‌توانید یک route را ابتدایی‌ترین واحد مسیریابی در نظر بگیرید.

  • آنها در طرح بندی ها (layouts) یا ناوبری‌های سمت کاربر مانند صفحه (page) شرکت نمی‌کنند.
  • در یک مسیر نمی‌توان همزمان فایل route.js و page.js داشت.
صفحهمسیرنتیجه
app/page.jsapp/route.jsConflict
app/page.jsapp/api/route.jsValid
app/[user]/page.jsapp/api/route.jsValid

هر فایل route.js یا page.js تمامی فعل‌های HTTP را برای آن مسیر کنترل می‌کند.

app/page.js
export default function Page() {
	return <h1>Hello, Next.js!</h1>
}
 
// ❌ Conflict
// `app/route.js`
export async function POST(request) {}

مثال ها

نمونه‌های زیر نحوه ترکیب هندلرهای مسیر با سایر API ها و ویژگی‌های Next.js را نشان می‌دهند.

باطل‌سازی مجدد داده‌های کش شده

می‌توانید داده‌های کش شده را با استفاده از گزینه next.revalidate باطل‌سازی مجدد کنید: revalidate cached data

app/items/route.ts
export async function GET() {
	const res = await fetch('https://data.mongodb-api.com/...', {
		next: { revalidate: 60 }, // Revalidate every 60 seconds
	})
	const data = await res.json()
 
	return Response.json(data)
}

به‌عنوان جایگزین، می‌توانید از گزینه پیکربندی بخش revalidate segment config option استفاده کنید:

export const revalidate = 60

توابع داینامیک

هندلرهای مسیر را می‌توان با توابع داینامیکی Next.js مانند cookies و headers استفاده کرد.

کوکی ها Cookies

با استفاده از cookies از next/headers می‌توانید کوکی‌ها را خوانده یا تنظیم کنید. این تابع سرور را می‌توان به صورت مستقیم درون یک هندلر مسیر فراخوانی کرد یا آن را درون تابع دیگری جایگذاری کرد.

به‌عنوان جایگزین، می‌توانید یک Response جدید با استفاده از هدر Set-Cookie (opens in a new tab) برگردانید.

app/api/route.ts
import { cookies } from 'next/headers'
 
export async function GET(request: Request) {
	const cookieStore = cookies()
	const token = cookieStore.get('token')
 
	return new Response('Hello, Next.js!', {
		status: 200,
		headers: { 'Set-Cookie': `token=${token.value}` },
	})
}

به‌عنوان جایگزین دیگری، می‌توانید از API‌های وب پایه‌ای برای خواندن کوکی‌ها از درخواست (NextRequest) استفاده کنید.

app/api/route.ts
import { type NextRequest } from 'next/server'
 
export async function GET(request: NextRequest) {
	const token = request.cookies.get('token')
}

هدرها Headers

می‌توانید هدرها را با استفاده از headers از next/headers بخوانید. این تابع سرور را می‌توان به صورت مستقیم درون یک هندلر مسیر فراخوانی کرد یا آن را درون تابع دیگری جایگذاری کرد.

این نمونه headers فقط برای خواندن است. برای تنظیم هدرها، نیاز است یک Response جدید با headers هدرهای جدید برگردانید.

app/api/route.ts
import { headers } from 'next/headers'
 
export async function GET(request: Request) {
	const headersList = headers()
	const referer = headersList.get('referer')
 
	return new Response('Hello, Next.js!', {
		status: 200,
		headers: { referer: referer },
	})
}

به‌عنوان جایگزین دیگری، می‌توانید از API‌های وب پایه‌ای برای خواندن هدرها از درخواست (NextRequest) استفاده کنید.

app/api/route.ts
import { type NextRequest } from 'next/server'
 
export async function GET(request: NextRequest) {
	const requestHeaders = new Headers(request.headers)
}

ریدایرکت ها

app/api/route.ts
import { redirect } from 'next/navigation'
 
export async function GET(request: Request) {
	redirect('https://nextjs.org/')
}

بخش های مسیر داینامیک

پیشنهاد می‌کنیم قبل از ادامه، صفحه‌ی تعریف مسیرها را مطالعه کنید.

هندلرهای مسیر می‌توانند از Dynamic Segments برای ایجاد مدیریت درخواست‌ها بر اساس داده‌های داینامیک استفاده کنند.

app/items/[slug]/route.ts
export async function GET(
	request: Request,
	{ params }: { params: { slug: string } }
) {
	const slug = params.slug // 'a', 'b', or 'c'
}
مسیرURL مثالparams
app/items/[slug]/route.js/items/a{ slug: 'a' }
app/items/[slug]/route.js/items/b{ slug: 'b' }
app/items/[slug]/route.js/items/c{ slug: 'c' }

کوئری پارامترهای URL

شیء درخواستی (request object) که به هندلر مسیر پاس داده می‌شود، یک نمونه از NextRequest است که حاوی برخی متدهای راحتی اضافی برای مدیریت آسان‌تر پارامترهای کوئری URL می‌باشد.

app/api/search/route.ts
import { type NextRequest } from 'next/server'
 
export function GET(request: NextRequest) {
	const searchParams = request.nextUrl.searchParams
	const query = searchParams.get('query')
	// query is "hello" for /api/search?query=hello
}

استریمینگ

استریمینگ اغلب در ترکیب با مدل‌های زبان بزرگ (LLMs) مانند OpenAI برای محتوای تولیدشده توسط هوش مصنوعی استفاده می‌شود. برای کسب اطلاعات بیشتر در مورد SDK هوش مصنوعی، اینجا AI SDK (opens in a new tab) را مطالعه کنید.

app/api/chat/route.ts
import { openai } from '@ai-sdk/openai'
import { StreamingTextResponse, streamText } from 'ai'
 
export async function POST(req: Request) {
	const { messages } = await req.json()
	const result = await streamText({
		model: openai('gpt-4-turbo'),
		messages,
	})
 
	return new StreamingTextResponse(result.toAIStream())
}

این انتزاعیات (abstractions) از API‌های وب برای ایجاد استریم استفاده می‌کنند. همچنین می‌توانید به صورت مستقیم از API‌های وب پایه‌ای استفاده کنید.

app/api/route.ts
// https://developer.mozilla.org/nextjs/Web/API/ReadableStream#convert_async_iterator_to_stream
function iteratorToStream(iterator: any) {
	return new ReadableStream({
		async pull(controller) {
			const { value, done } = await iterator.next()
 
			if (done) {
				controller.close()
			} else {
				controller.enqueue(value)
			}
		},
	})
}
 
function sleep(time: number) {
	return new Promise((resolve) => {
		setTimeout(resolve, time)
	})
}
 
const encoder = new TextEncoder()
 
async function* makeIterator() {
	yield encoder.encode('<p>One</p>')
	await sleep(200)
	yield encoder.encode('<p>Two</p>')
	await sleep(200)
	yield encoder.encode('<p>Three</p>')
}
 
export async function GET() {
	const iterator = makeIterator()
	const stream = iteratorToStream(iterator)
 
	return new Response(stream)
}

بدنه درخواست Request Body

می‌توانید بدنه درخواست را با استفاده از متدهای استاندارد API وب بخوانید:

app/items/route.ts
export async function POST(request: Request) {
	const res = await request.json()
	return Response.json({ res })
}

بدنه درخواست FormData

می‌توانید داده‌های فرم FormData را با استفاده از تابع request.formData() بخوانید.

app/items/route.ts
export async function POST(request: Request) {
	const formData = await request.formData()
	const name = formData.get('name')
	const email = formData.get('email')
	return Response.json({ name, email })
}

از آنجایی که داده های formData همه رشته ها هستند، برای اعتبارسنجی و دریافت داده در قالب دلخواه (مثلا number) از zod-form-data (opens in a new tab) استفاده کنید.

CORS (Cross-origin resource sharing)

می‌توانید از روش‌های استاندارد API وب برای تنظیم هدرهای CORS برای یک هندلر مسیر خاص استفاده کنید :

app/api/route.ts
export const dynamic = 'force-dynamic' // defaults to auto
 
export async function GET(request: Request) {
	return new Response('Hello, Next.js!', {
		status: 200,
		headers: {
			'Access-Control-Allow-Origin': '*',
			'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
			'Access-Control-Allow-Headers': 'Content-Type, Authorization',
		},
	})
}

خوب است بدانید:

وب هوک ها Webhooks

وب‌سرویس‌های شخص ثالث می‌توانند از طریق یک هندلر مسیر برای شما وب‌هوک ارسال کنند.

app/api/route.ts
export async function POST(request: Request) {
	try {
		const text = await request.text()
		// Process the webhook payload
	} catch (error) {
		return new Response(`Webhook error: ${error.message}`, {
			status: 400,
		})
	}
 
	return new Response('Success!', {
		status: 200,
	})
}

قابل‌توجه است که برخلاف مسیرهای API با Pages Router، برای استفاده از هندلر مسیر به هیچ پیکربندی اضافی یا استفاده از bodyParser نیاز ندارید.

پاسخ‌های بدون رابط کاربری Non-UI Responses

می‌توانید از هندلر مسیر برای برگرداندن محتوای غیر-رابط کاربری استفاده کنید. توجه داشته باشید که sitemap.xml، robots.txt، آیکون های برنامه و تصاویر open graph همگی از پشتیبانی داخلی برخوردار هستند.

app/rss.xml/route.ts
export const dynamic = 'force-dynamic' // defaults to auto
 
export async function GET() {
	return new Response(
		`<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
 
<channel>
  <title>Next.js Documentation</title>
  <link>https://nextjs.org/docs</link>
  <description>The React Framework for the Web</description>
</channel>
 
</rss>`,
		{
			headers: {
				'Content-Type': 'text/xml',
			},
		}
	)
}

گزینه های پیکربندی بخش

هندلرهای مسیر از همان پیکربندی بخش مسیر route segment configuration صفحات و چیدمان‌ها استفاده می‌کنند.

app/items/route.ts
export const dynamic = 'auto'
export const dynamicParams = true
export const revalidate = false
export const fetchCache = 'auto'
export const runtime = 'nodejs'
export const preferredRegion = 'auto'

برای جزئیات بیشتر به مرجع API مراجعه کنید.