العربية

تعلم كيفية إنشاء نقاط نهاية API قوية باستخدام معالجات التوجيه في Next.js. يغطي هذا الدليل كل شيء بدءًا من الإعداد الأساسي إلى التقنيات المتقدمة، مع أمثلة عملية وأفضل الممارسات.

معالجات التوجيه في Next.js: دليل شامل لإنشاء نقاط نهاية API

أحدث إطار العمل Next.js ثورة في طريقة بناء تطبيقات الويب بميزاته القوية مثل العرض من جانب الخادم، وتوليد المواقع الثابتة، والآن، معالجات التوجيه (Route Handlers). توفر معالجات التوجيه طريقة مرنة وفعالة لإنشاء نقاط نهاية API مباشرة داخل تطبيق Next.js الخاص بك. يستكشف هذا الدليل مفهوم معالجات التوجيه وفوائدها وكيفية استخدامها بفعالية لبناء واجهات برمجة تطبيقات (APIs) قوية.

ما هي معالجات التوجيه في Next.js؟

معالجات التوجيه هي دوال يتم تعريفها داخل مجلد app في مشروع Next.js لمعالجة طلبات HTTP الواردة. على عكس النهج القديم pages/api (الذي يستخدم مسارات API)، تقدم معالجات التوجيه طريقة أكثر تبسيطًا ومرونة لتعريف نقاط نهاية API إلى جانب مكونات React الخاصة بك. هي في الأساس دوال بلا خادم (serverless functions) يتم تنفيذها على الحافة (edge) أو بيئة الخادم التي تختارها.

فكر في معالجات التوجيه على أنها المنطق الخلفي لتطبيق Next.js الخاص بك، والمسؤولة عن معالجة الطلبات، والتفاعل مع قواعد البيانات، وإرجاع الاستجابات.

فوائد استخدام معالجات التوجيه

إعداد مشروع Next.js الخاص بك

قبل الغوص في معالجات التوجيه، تأكد من أن لديك مشروع Next.js تم إعداده باستخدام مجلد app. إذا كنت تبدأ مشروعًا جديدًا، فاستخدم الأمر التالي:

npx create-next-app@latest my-nextjs-app

اختر مجلد app أثناء عملية الإعداد لتمكين نظام التوجيه الجديد.

إنشاء أول معالج توجيه لك

لنقم بإنشاء نقطة نهاية API بسيطة تعيد استجابة JSON. أنشئ مجلدًا جديدًا داخل مجلد app، على سبيل المثال، /app/api/hello. داخل هذا المجلد، أنشئ ملفًا باسم route.ts (أو route.js إذا كنت لا تستخدم TypeScript).

إليك كود أول معالج توجيه لك:

// app/api/hello/route.ts
import { NextResponse } from 'next/server';

export async function GET(request: Request) {
 return NextResponse.json({ message: 'Hello from Next.js Route Handlers!' });
}

شرح الكود:

الآن، يمكنك الوصول إلى نقطة النهاية هذه عن طريق الانتقال إلى /api/hello في متصفحك أو استخدام أداة مثل curl أو Postman.

التعامل مع طرق HTTP المختلفة

تدعم معالجات التوجيه طرق HTTP المختلفة مثل GET و POST و PUT و DELETE و PATCH و OPTIONS. يمكنك تعريف دوال منفصلة لكل طريقة داخل نفس ملف route.ts.

// app/api/users/route.ts
import { NextResponse } from 'next/server';

export async function GET(request: Request) {
 // Logic to retrieve all users from the database
 const users = [{ id: 1, name: 'John Doe' }, { id: 2, name: 'Jane Smith' }]; // Example data
 return NextResponse.json(users);
}

export async function POST(request: Request) {
 const data = await request.json(); // Parse the request body as JSON
 // Logic to create a new user in the database using 'data'
 const newUser = { id: 3, name: data.name, email: data.email }; // Example
 return NextResponse.json(newUser, { status: 201 }); // Return the new user with a 201 Created status code
}

شرح الكود:

الوصول إلى بيانات الطلب

يوفر كائن request الوصول إلى معلومات مختلفة حول الطلب الوارد، بما في ذلك الترويسات (headers)، ومعلمات الاستعلام (query parameters)، ونص الطلب.

الترويسات (Headers)

يمكنك الوصول إلى ترويسات الطلب باستخدام خاصية request.headers:

export async function GET(request: Request) {
 const userAgent = request.headers.get('user-agent');
 console.log('User Agent:', userAgent);
 return NextResponse.json({ userAgent });
}

معلمات الاستعلام (Query Parameters)

للوصول إلى معلمات الاستعلام، يمكنك استخدام مُنشئ URL:

export async function GET(request: Request) {
 const url = new URL(request.url);
 const searchParams = new URLSearchParams(url.search);
 const id = searchParams.get('id');
 console.log('ID:', id);
 return NextResponse.json({ id });
}

نص الطلب (Request Body)

بالنسبة لطلبات POST و PUT و PATCH، يمكنك الوصول إلى نص الطلب باستخدام أساليب request.json() أو request.text()، اعتمادًا على نوع المحتوى.

export async function POST(request: Request) {
 const data = await request.json();
 console.log('Data:', data);
 return NextResponse.json({ receivedData: data });
}

إرجاع الاستجابات

يستخدم كائن NextResponse لإنشاء استجابات API. ويوفر عدة طرق لتعيين الترويسات ورموز الحالة ونصوص الاستجابة.

استجابات JSON

استخدم طريقة NextResponse.json() لإرجاع استجابات JSON:

return NextResponse.json({ message: 'Success!', data: { name: 'John Doe' } }, { status: 200 });

استجابات نصية

استخدم مُنشئ new Response() لإرجاع استجابات نصية عادية:

return new Response('Hello, world!', { status: 200, headers: { 'Content-Type': 'text/plain' } });

إعادة التوجيه (Redirects)

استخدم NextResponse.redirect() لإعادة توجيه المستخدمين إلى عنوان URL مختلف:

import { redirect } from 'next/navigation';
import { NextResponse } from 'next/server';

export async function GET(request: Request) {
 return NextResponse.redirect(new URL('/new-location', request.url));
}

تعيين الترويسات (Headers)

يمكنك تعيين ترويسات مخصصة باستخدام خيار headers في NextResponse.json() أو new Response():

return NextResponse.json({ message: 'Success!' }, { status: 200, headers: { 'Cache-Control': 'no-cache' } });

التكامل مع الوسيط (Middleware)

يسمح لك الوسيط (Middleware) بتشغيل كود قبل معالجة الطلب بواسطة معالج التوجيه الخاص بك. هذا مفيد للمصادقة والترخيص والتسجيل وغيرها من الاهتمامات الشاملة (cross-cutting concerns).

لإنشاء وسيط، أنشئ ملفًا باسم middleware.ts (أو middleware.js) في مجلد app أو أي مجلد فرعي. سيتم تطبيق الوسيط على جميع المسارات داخل ذلك المجلد ومجلداته الفرعية.

// app/middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
 const token = request.cookies.get('auth-token');

 if (!token) {
 return NextResponse.redirect(new URL('/login', request.url));
 }

 return NextResponse.next();
}

export const config = {
 matcher: ['/protected/:path*'], // Apply this middleware to paths starting with /protected/
};

شرح الكود:

معالجة الأخطاء

تعتبر معالجة الأخطاء بشكل صحيح أمرًا بالغ الأهمية لبناء واجهات برمجة تطبيقات قوية. يمكنك استخدام كتل try...catch لمعالجة الاستثناءات وإرجاع استجابات خطأ مناسبة.

export async function GET(request: Request) {
 try {
 // Simulate an error
 throw new Error('Something went wrong!');
 } catch (error: any) {
 console.error('Error:', error);
 return NextResponse.json({ error: error.message }, { status: 500 });
 }
}

شرح الكود:

الاستجابات المتدفقة (Streaming Responses)

تدعم معالجات التوجيه الاستجابات المتدفقة، مما يسمح لك بإرسال البيانات بشكل تدريجي إلى العميل. هذا مفيد بشكل خاص لمجموعات البيانات الكبيرة أو العمليات طويلة الأمد.

import { Readable } from 'stream';
import { NextResponse } from 'next/server';

async function* generateData() {
 for (let i = 0; i < 10; i++) {
 await new Promise(resolve => setTimeout(resolve, 500)); // Simulate delay
 yield `Data chunk ${i}\n`;
 }
}

export async function GET(request: Request) {
 const readableStream = Readable.from(generateData());

 return new Response(readableStream, {
 headers: { 'Content-Type': 'text/plain; charset=utf-8' },
 });
}

شرح الكود:

المصادقة والترخيص

يعد تأمين نقاط نهاية API الخاصة بك أمرًا بالغ الأهمية. يمكنك تنفيذ المصادقة والترخيص باستخدام الوسيط (middleware) أو مباشرة داخل معالجات التوجيه الخاصة بك.

المصادقة (Authentication)

المصادقة تتحقق من هوية المستخدم الذي يقوم بالطلب. تشمل طرق المصادقة الشائعة ما يلي:

إليك مثال على مصادقة JWT باستخدام الوسيط:

// app/middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import jwt from 'jsonwebtoken';

const secret = process.env.JWT_SECRET || 'your-secret-key'; // Replace with a strong, randomly generated secret

export function middleware(request: NextRequest) {
 const token = request.cookies.get('auth-token')?.value;

 if (!token) {
 return NextResponse.json({ message: 'Authentication required' }, { status: 401 });
 }

 try {
 jwt.verify(token, secret);
 return NextResponse.next();
 } catch (error) {
 return NextResponse.json({ message: 'Invalid token' }, { status: 401 });
 }
}

export const config = {
 matcher: ['/api/protected/:path*'],
};

الترخيص (Authorization)

يحدد الترخيص الموارد المسموح للمستخدم بالوصول إليها. يعتمد هذا عادةً على الأدوار أو الأذونات.

يمكنك تنفيذ الترخيص داخل معالجات التوجيه الخاصة بك عن طريق التحقق من أدوار المستخدم أو أذوناته وإرجاع خطأ إذا لم يكن لديهم حق الوصول.

// app/api/admin/route.ts
import { NextResponse } from 'next/server';

export async function GET(request: Request) {
 // Assume you have a function to get the user's role from the token or session
 const userRole = await getUserRole(request);

 if (userRole !== 'admin') {
 return NextResponse.json({ message: 'Unauthorized' }, { status: 403 });
 }

 // Logic to retrieve admin data
 const adminData = { message: 'Admin data' };
 return NextResponse.json(adminData);
}

async function getUserRole(request: Request): Promise {
 // Replace with your actual logic to extract the user's role from the request
 // This could involve verifying a JWT token or checking a session
 return 'admin'; // Example: hardcoded role for demonstration
}

نشر معالجات التوجيه

يتم نشر معالجات التوجيه كدوال بلا خادم (serverless functions) على مزود الاستضافة الذي تختاره. يدعم Next.js منصات نشر مختلفة، بما في ذلك Vercel و Netlify و AWS وغيرها.

بالنسبة لـ Vercel، يكون النشر بسيطًا مثل توصيل مستودع Git الخاص بك بـ Vercel ودفع الكود الخاص بك. يكتشف Vercel تلقائيًا مشروع Next.js الخاص بك وينشر معالجات التوجيه الخاصة بك كدوال بلا خادم.

تقنيات متقدمة

دوال الحافة (Edge Functions)

يمكن نشر معالجات التوجيه كدوال حافة (Edge Functions)، والتي يتم تنفيذها على حافة شبكة توصيل المحتوى (CDN)، أقرب إلى المستخدمين. هذا يمكن أن يقلل بشكل كبير من زمن الوصول ويحسن الأداء.

لنشر معالج توجيه كدالة حافة، أضف وقت تشغيل edge إلى ملف route.ts الخاص بك:

export const runtime = 'edge';

import { NextResponse } from 'next/server';

export async function GET(request: Request) {
 return NextResponse.json({ message: 'Hello from the Edge!' });
}

إجراءات الخادم (Server Actions)

تسمح لك إجراءات الخادم بتنفيذ كود من جانب الخادم مباشرة من مكونات React الخاصة بك. تعمل معالجات التوجيه وإجراءات الخادم معًا بسلاسة، مما يتيح لك بناء تطبيقات معقدة بسهولة.

إليك مثال على استخدام إجراء خادم لاستدعاء معالج توجيه:

// app/components/MyComponent.tsx
'use client';
import { useState } from 'react';
import { useRouter } from 'next/navigation';

async function handleSubmit(data: FormData) {
 'use server';

 const name = data.get('name');
 const email = data.get('email');

 const response = await fetch('/api/users', {
 method: 'POST',
 body: JSON.stringify({ name, email }),
 });

 if (response.ok) {
 router.refresh(); // Refresh the page to reflect the changes
 }
}

export default function MyComponent() {
 const router = useRouter();

 return (
 




); }

التخزين المؤقت (Caching)

يمكن أن يحسن التخزين المؤقت أداء نقاط نهاية API بشكل كبير. يمكنك استخدام ترويسة Cache-Control للتحكم في كيفية تخزين استجاباتك مؤقتًا بواسطة المتصفحات وشبكات توصيل المحتوى.

return NextResponse.json({ message: 'Success!' }, { status: 200, headers: { 'Cache-Control': 'public, max-age=3600' } });

يعين هذا المثال ترويسة Cache-Control إلى public, max-age=3600، مما يخبر المتصفحات وشبكات توصيل المحتوى بتخزين الاستجابة مؤقتًا لمدة ساعة واحدة.

أفضل الممارسات

أمثلة من الواقع العملي

إليك بعض الأمثلة الواقعية لكيفية استخدام معالجات التوجيه:

مثال على التجارة الإلكترونية الدولية: معالج توجيه يستخدم لاسترداد أسعار المنتجات بناءً على بلد المستخدم. يمكن لنقطة النهاية استخدام الموقع الجغرافي للطلب (المشتق من عنوان IP) لتحديد موقع المستخدم وإرجاع الأسعار بالعملة المناسبة. هذا يساهم في تجربة تسوق محلية.

مثال على المصادقة العالمية: معالج توجيه يطبق المصادقة متعددة العوامل (MFA) للمستخدمين في جميع أنحاء العالم. قد يتضمن ذلك إرسال رموز SMS أو استخدام تطبيقات المصادقة، مع احترام لوائح الخصوصية والبنى التحتية للاتصالات في المناطق المختلفة.

توصيل المحتوى متعدد اللغات: معالج توجيه يقدم المحتوى باللغة المفضلة للمستخدم. يمكن تحديد ذلك من ترويسة `Accept-Language` في الطلب. يسلط هذا المثال الضوء على الحاجة إلى ترميز UTF-8 الصحيح ودعم اللغات من اليمين إلى اليسار عند الاقتضاء.

الخاتمة

توفر معالجات التوجيه في Next.js طريقة قوية ومرنة لإنشاء نقاط نهاية API مباشرة داخل تطبيق Next.js الخاص بك. من خلال الاستفادة من معالجات التوجيه، يمكنك بناء واجهات برمجة تطبيقات قوية بسهولة، وتجميع منطق الواجهة الخلفية مع مكونات React الخاصة بك، والاستفادة من ميزات مثل الوسيط (middleware)، والبث (streaming)، ودوال الحافة (Edge Functions).

لقد غطى هذا الدليل الشامل كل شيء بدءًا من الإعداد الأساسي إلى التقنيات المتقدمة. باتباع أفضل الممارسات الموضحة في هذا الدليل، يمكنك بناء واجهات برمجة تطبيقات عالية الجودة تكون آمنة وعالية الأداء وقابلة للصيانة.