Next.js
API Routes في Next.js — دليل شامل 2026
📅 2026-11-16⏱ 10 دقائق قراءة
في المقال السابق، تعلمت جلب البيانات. الآن سنتعلم **API Routes** — لبناء **Backend كامل** داخل Next.js.
في هذا الدليل العملي، سنأخذك خطوة بخطوة لفهم API Routes، مع تمارين وحلول.
## ما هي API Routes؟
**API Routes** هي **نقاط نهاية (Endpoints)** تبنيها داخل Next.js، دون الحاجة لسيرفر منفصل.
**الفائدة:**
- ✅ نفس المشروع (Frontend + Backend).
- ✅ نشر واحد.
- ✅ TypeScript مشترك.
- ✅ لا CORS.
**متى تستخدمها؟**
- **عندما تحتاج API** لتطبيقك.
- **عندما تريد دمج البيانات** من مصادر متعددة.
- **عندما تحتاج التحقق من البيانات** قبل الإرسال.
- **عندما تريد حماية API Keys.**
## Route Handlers
في App Router، تُسمى **Route Handlers** وتوضع في ملف `route.ts`.
<table>
<thead>
<tr>
<th>المسار</th>
<th>الملف</th>
<th>الرابط</th>
</tr>
</thead>
<tbody>
<tr>
<td>API أساسي</td>
<td><code>app/api/route.ts</code></td>
<td><code>/api</code></td>
</tr>
<tr>
<td>API للمستخدمين</td>
<td><code>app/api/users/route.ts</code></td>
<td><code>/api/users</code></td>
</tr>
<tr>
<td>API للمستخدم الواحد</td>
<td><code>app/api/users/[id]/route.ts</code></td>
<td><code>/api/users/1</code></td>
</tr>
<tr>
<td>API للمقالات</td>
<td><code>app/api/posts/route.ts</code></td>
<td><code>/api/posts</code></td>
</tr>
</tbody>
</table>
## أول API
**`app/api/hello/route.ts`:**
```tsx
import { NextResponse } from "next/server";
export async function GET() {
return NextResponse.json({
message: "مرحباً من Next.js API!",
timestamp: new Date().toISOString(),
});
}
```
**الاختبار:**
```
GET http://localhost:3000/api/hello
```
**النتيجة:**
```json
{
"message": "مرحباً من Next.js API!",
"timestamp": "2026-11-16T10:30:00.000Z"
}
```
**🎉 مبروك! بنيت أول API!**
## طرق HTTP
**`app/api/users/route.ts`:**
```tsx
import { NextResponse } from "next/server";
// GET /api/users
export async function GET() {
return NextResponse.json([
{ id: 1, name: "أحمد" },
{ id: 2, name: "محمد" },
]);
}
// POST /api/users
export async function POST(request: Request) {
const body = await request.json();
return NextResponse.json(
{ success: true, user: body },
{ status: 201 }
);
}
// PUT /api/users
export async function PUT(request: Request) {
const body = await request.json();
return NextResponse.json({ success: true, user: body });
}
// DELETE /api/users
export async function DELETE() {
return NextResponse.json({ success: true });
}
// PATCH /api/users
export async function PATCH(request: Request) {
const body = await request.json();
return NextResponse.json({ success: true, patch: body });
}
// HEAD / OPTIONS (تلقائي)
```
## قراءة الطلبات
### 1. قراءة Body (JSON)
```tsx
export async function POST(request: Request) {
const body = await request.json();
return NextResponse.json({ received: body });
}
```
### 2. قراءة Body (Form)
```tsx
export async function POST(request: Request) {
const formData = await request.formData();
const name = formData.get("name") as string;
return NextResponse.json({ name });
}
```
### 3. قراءة Query Parameters
```tsx
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const query = searchParams.get("q");
const limit = searchParams.get("limit");
return NextResponse.json({ query, limit });
}
```
**الاختبار:** `/api/search?q=react&limit=5`
### 4. قراءة Route Parameters
**`app/api/users/[id]/route.ts`:**
```tsx
export async function GET(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
const { id } = await params;
return NextResponse.json({ id, name: `المستخدم ${id}` });
}
```
**⚠️ لاحظ:** في Next.js 15، `params` هو Promise.
### 5. قراءة Headers
```tsx
export async function GET(request: Request) {
const auth = request.headers.get("authorization");
return NextResponse.json({ auth });
}
```
## إرسال الاستجابات
### 1. JSON
```tsx
return NextResponse.json({ message: "مرحباً" });
```
### 2. مع Status Code
```tsx
return NextResponse.json(
{ error: "غير موجود" },
{ status: 404 }
);
```
### 3. مع Headers
```tsx
return NextResponse.json(
{ message: "مرحباً" },
{
headers: {
"Cache-Control": "no-store",
"X-Custom-Header": "value",
},
}
);
```
### 4. نصوص
```tsx
return new Response("نص عادي", {
headers: { "Content-Type": "text/plain; charset=utf-8" },
});
```
### 5. إعادة توجيه
```tsx
import { redirect } from "next/navigation";
export async function GET() {
redirect("/");
}
```
## أكواد الحالة
<table>
<thead>
<tr>
<th>الكود</th>
<th>المعنى</th>
<th>الاستخدام</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>200</strong></td>
<td>OK</td>
<td>نجاح</td>
</tr>
<tr>
<td><strong>201</strong></td>
<td>Created</td>
<td>إنشاء</td>
</tr>
<tr>
<td><strong>204</strong></td>
<td>No Content</td>
<td>حذف</td>
</tr>
<tr>
<td><strong>400</strong></td>
<td>Bad Request</td>
<td>طلب خاطئ</td>
</tr>
<tr>
<td><strong>401</strong></td>
<td>Unauthorized</td>
<td>غير مصرح</td>
</tr>
<tr>
<td><strong>403</strong></td>
<td>Forbidden</td>
<td>ممنوع</td>
</tr>
<tr>
<td><strong>404</strong></td>
<td>Not Found</td>
<td>غير موجود</td>
</tr>
<tr>
<td><strong>500</strong></td>
<td>Internal Server Error</td>
<td>خطأ في السيرفر</td>
</tr>
</tbody>
</table>
## مثال عملي: CRUD للمستخدمين
**`app/api/users/route.ts`:**
```tsx
import { NextResponse } from "next/server";
let users = [
{ id: 1, name: "أحمد", email: "ahmed@example.com" },
{ id: 2, name: "محمد", email: "mohamed@example.com" },
];
// GET /api/users
export async function GET() {
return NextResponse.json(users);
}
// POST /api/users
export async function POST(request: Request) {
const body = await request.json();
if (!body.name || !body.email) {
return NextResponse.json(
{ error: "الاسم والبريد مطلوبان" },
{ status: 400 }
);
}
const newUser = {
id: Date.now(),
name: body.name,
email: body.email,
};
users.push(newUser);
return NextResponse.json(newUser, { status: 201 });
}
```
**`app/api/users/[id]/route.ts`:**
```tsx
import { NextResponse } from "next/server";
let users = [
{ id: 1, name: "أحمد", email: "ahmed@example.com" },
{ id: 2, name: "محمد", email: "mohamed@example.com" },
];
// GET /api/users/:id
export async function GET(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
const { id } = await params;
const user = users.find((u) => u.id === parseInt(id));
if (!user) {
return NextResponse.json(
{ error: "المستخدم غير موجود" },
{ status: 404 }
);
}
return NextResponse.json(user);
}
// PUT /api/users/:id
export async function PUT(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
const { id } = await params;
const body = await request.json();
const index = users.findIndex((u) => u.id === parseInt(id));
if (index === -1) {
return NextResponse.json(
{ error: "المستخدم غير موجود" },
{ status: 404 }
);
}
users[index] = { ...users[index], ...body };
return NextResponse.json(users[index]);
}
// DELETE /api/users/:id
export async function DELETE(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
const { id } = await params;
const index = users.findIndex((u) => u.id === parseInt(id));
if (index === -1) {
return NextResponse.json(
{ error: "المستخدم غير موجود" },
{ status: 404 }
);
}
users.splice(index, 1);
return new NextResponse(null, { status: 204 });
}
```
## التحقق من البيانات
```tsx
export async function POST(request: Request) {
const body = await request.json();
const errors = [];
if (!body.name || body.name.length < 2) {
errors.push("الاسم يجب أن يكون حرفين على الأقل");
}
if (!body.email || !body.email.includes("@")) {
errors.push("البريد غير صحيح");
}
if (body.age && (body.age < 18 || body.age > 100)) {
errors.push("العمر يجب أن يكون بين 18 و 100");
}
if (errors.length > 0) {
return NextResponse.json(
{ errors },
{ status: 400 }
);
}
// ... إنشاء المستخدم
}
```
## استخدام API من Client
### 1. استخدام fetch
```tsx
"use client";
import { useState, useEffect } from "react";
export default function UsersList() {
const [users, setUsers] = useState([]);
useEffect(() => {
fetch("/api/users")
.then((res) => res.json())
.then(setUsers);
}, []);
return (
<ul>
{users.map((u) => (
<li key={u.id}>{u.name}</li>
))}
</ul>
);
}
```
### 2. إرسال POST
```tsx
"use client";
async function createUser(name: string, email: string) {
const res = await fetch("/api/users", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name, email }),
});
const data = await res.json();
return data;
}
```
## مثال: API للبحث
**`app/api/search/route.ts`:**
```tsx
import { NextResponse } from "next/server";
const articles = [
{ id: 1, title: "تعلم Next.js", category: "برمجة" },
{ id: 2, title: "تعلم React", category: "برمجة" },
{ id: 3, title: "تعلم TypeScript", category: "برمجة" },
];
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const q = searchParams.get("q") || "";
const results = articles.filter((article) =>
article.title.toLowerCase().includes(q.toLowerCase())
);
return NextResponse.json({
query: q,
count: results.length,
results,
});
}
```
**الاختبار:** `/api/search?q=react`
## تمارين عملية
### تمرين 1: API بسيط
أنشئ `/api/hello` يعيد ترحيباً.
**الحل:**
```tsx
import { NextResponse } from "next/server";
export async function GET() {
return NextResponse.json({ message: "مرحباً" });
}
```
### تمرين 2: GET مع Query
أنشئ API يقرأ `?name=`.
**الحل:**
```tsx
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const name = searchParams.get("name") || "زائر";
return NextResponse.json({ message: `مرحباً ${name}` });
}
```
### تمرين 3: POST
أنشئ API يستقبل JSON.
**الحل:**
```tsx
export async function POST(request: Request) {
const body = await request.json();
return NextResponse.json({ received: body }, { status: 201 });
}
```
### تمرين 4: CRUD كامل
أنشئ CRUD للمقالات.
**الحل:**
```tsx
// app/api/posts/route.ts
let posts = [];
export async function GET() {
return NextResponse.json(posts);
}
export async function POST(request: Request) {
const body = await request.json();
const post = { id: Date.now(), ...body };
posts.push(post);
return NextResponse.json(post, { status: 201 });
}
```
### تمرين 5: مسار ديناميكي
أنشئ `/api/users/[id]`.
**الحل:**
```tsx
export async function GET(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
const { id } = await params;
return NextResponse.json({ id });
}
```
### تمرين 6: التحقق
أضف تحققاً للبيانات.
**الحل:**
```tsx
if (!body.email?.includes("@")) {
return NextResponse.json(
{ error: "بريد غير صحيح" },
{ status: 400 }
);
}
```
### تمرين 7: حماية API
أضف تحقق من Authorization.
**الحل:**
```tsx
export async function POST(request: Request) {
const auth = request.headers.get("authorization");
if (auth !== "Bearer secret-token") {
return NextResponse.json(
{ error: "غير مصرح" },
{ status: 401 }
);
}
// ...
}
```
### تمرين 8: API متكامل
ابنِ API كامل مع CRUD + تحقق + حماية.
**الحل:** (راجع المثال الكامل أعلاه)
## حل المشاكل الشائعة
### 🔴 المشكلة 1: API لا يعمل في Client
**السبب:** استخدام URL غير كامل.
**الحل:** استخدم URL نسبي:
```tsx
fetch("/api/users"); // ✅
```
### 🔴 المشكلة 2: `request.json()` يفشل
**السبب:** Body فارغ أو غير JSON.
**الحل:**
```tsx
try {
const body = await request.json();
} catch {
return NextResponse.json({ error: "JSON غير صحيح" }, { status: 400 });
}
```
### 🔴 المشكلة 3: CORS
**السبب:** الطلب من نطاق مختلف.
**الحل:** أضف headers:
```tsx
return NextResponse.json(data, {
headers: {
"Access-Control-Allow-Origin": "*",
},
});
```
### 🔴 المشكلة 4: API Routes لا تعمل مع `output: 'export'`
**السبب:** التصدير الثابت لا يدعم API Routes.
**الحل:** استخدم Vercel أو Firebase Functions.
### 🔴 المشكلة 5: `params` غير متاح
**السبب:** في Next.js 15، `params` هو Promise.
**الحل:**
```tsx
{ params }: { params: Promise<{ id: string }> }
// ...
const { id } = await params;
```
## جدول دوال API
<table>
<thead>
<tr>
<th>الدالة</th>
<th>الوظيفة</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>NextResponse.json()</code></td>
<td>إرسال JSON</td>
</tr>
<tr>
<td><code>request.json()</code></td>
<td>قراءة JSON</td>
</tr>
<tr>
<td><code>request.formData()</code></td>
<td>قراءة Form</td>
</tr>
<tr>
<td><code>request.headers.get()</code></td>
<td>قراءة Header</td>
</tr>
<tr>
<td><code>new URL(request.url)</code></td>
<td>قراءة Query</td>
</tr>
<tr>
<td><code>new Response()</code></td>
<td>استجابة مخصصة</td>
</tr>
<tr>
<td><code>redirect()</code></td>
<td>إعادة توجيه</td>
</tr>
</tbody>
</table>
## قائمة تحقق نهائية
<table>
<thead>
<tr>
<th>المهمة</th>
<th>الحالة</th>
</tr>
</thead>
<tbody>
<tr>
<td>فهم Route Handlers</td>
<td>⬜</td>
</tr>
<tr>
<td>GET و POST</td>
<td>⬜</td>
</tr>
<tr>
<td>قراءة Body و Query</td>
<td>⬜</td>
</tr>
<tr>
<td>المسارات الديناميكية</td>
<td>⬜</td>
</tr>
<tr>
<td>التحقق من البيانات</td>
<td>⬜</td>
</tr>
<tr>
<td>حماية API</td>
<td>⬜</td>
</tr>
<tr>
<td>حل التمارين الثمانية</td>
<td>⬜</td>
</tr>
</tbody>
</table>
## ماذا بعد هذا المقال؟
الآن بعد أن أتقنت API Routes، أنت جاهز للمقال التالي:
1. **Styling** — Tailwind و CSS.
2. **Authentication** — المصادقة.
3. **Deployment** — النشر.
## الخلاصة
في هذا المقال، تعلمت:
- ✅ ما هي API Routes.
- ✅ Route Handlers.
- ✅ طرق HTTP.
- ✅ قراءة الطلبات.
- ✅ إرسال الاستجابات.
- ✅ CRUD كامل.
- ✅ التحقق من البيانات.
- ✅ حل 8 تمارين عملية.
**تذكر:** API Routes تجعل Next.js **إطاراً كاملاً** — Frontend و Backend.