ما هي واجهات برمجة التطبيقات (API)؟
تخيل أنك في مطعم. أنت (التطبيق) تريد طعاماً (بيانات) من المطبخ (الخادم). API هو النادل الذي يأخذ طلبك ويحضر لك ما تريد. لا تحتاج لمعرفة كيف يُطبخ الطعام — فقط ترسل طلبك وتحصل على النتيجة.
REST API (Representational State Transfer) هي النمط الأكثر شيوعاً لبناء واجهات برمجة التطبيقات. تستخدمها تقريباً كل المواقع والتطبيقات التي تتعامل معها يومياً.
المفاهيم الأساسية في REST
أفعال HTTP
كل طلب يستخدم فعل HTTP يحدد نوع العملية:
- GET: جلب بيانات — « أعطني قائمة المنتجات »
- POST: إنشاء بيانات جديدة — « أضف منتجاً جديداً »
- PUT/PATCH: تحديث بيانات — « عدّل سعر هذا المنتج »
- DELETE: حذف بيانات — « احذف هذا المنتج »
أكواد الحالة (Status Codes)
- 200 OK: الطلب نجح
- 201 Created: تم إنشاء مورد جديد
- 400 Bad Request: الطلب غير صحيح
- 401 Unauthorized: غير مصرح لك
- 404 Not Found: المورد غير موجود
- 500 Internal Server Error: خطأ في الخادم
هيكل URL في REST
# الموارد (Resources) - أسماء جمع
GET /api/products → جلب كل المنتجات
GET /api/products/123 → جلب المنتج رقم 123
POST /api/products → إنشاء منتج جديد
PUT /api/products/123 → تحديث المنتج رقم 123
DELETE /api/products/123 → حذف المنتج رقم 123
# الفلترة والترتيب
GET /api/products?category=electronics&sort=price&limit=10
GET /api/products?page=2&per_page=20
تطبيق عملي: التعامل مع API باستخدام JavaScript
1. جلب بيانات (GET)
// جلب قائمة المنتجات
async function getProducts() {
try {
const response = await fetch('https://fakestoreapi.com/products');
if (!response.ok) {
throw new Error(`خطأ: ${response.status}`);
}
const products = await response.json();
console.log(`تم جلب ${products.length} منتج`);
return products;
} catch (error) {
console.error('فشل جلب المنتجات:', error.message);
}
}
// جلب منتج واحد
async function getProduct(id) {
const response = await fetch(`https://fakestoreapi.com/products/${id}`);
return response.json();
}
2. إرسال بيانات (POST)
async function createProduct(productData) {
try {
const response = await fetch('https://fakestoreapi.com/products', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(productData)
});
const newProduct = await response.json();
console.log('تم إنشاء المنتج:', newProduct);
return newProduct;
} catch (error) {
console.error('فشل الإنشاء:', error.message);
}
}
// الاستخدام
createProduct({
title: "هاتف ذكي جديد",
price: 499.99,
description: "هاتف بمواصفات عالية",
category: "electronics"
});
3. تحديث بيانات (PUT)
async function updateProduct(id, updates) {
const response = await fetch(`https://fakestoreapi.com/products/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(updates)
});
return response.json();
}
updateProduct(1, { price: 399.99 });
4. حذف بيانات (DELETE)
async function deleteProduct(id) {
const response = await fetch(`https://fakestoreapi.com/products/${id}`, {
method: 'DELETE'
});
if (response.ok) {
console.log(`تم حذف المنتج ${id}`);
}
}
مشروع تطبيقي: عرض منتجات من API حقيقي
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<title>متجر المنتجات</title>
<style>
.products { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 1.5rem; padding: 2rem; }
.product { background: white; border-radius: 10px; padding: 1rem; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
.product img { width: 100%; height: 200px; object-fit: contain; }
.price { color: #e94560; font-size: 1.25rem; font-weight: bold; }
.loading { text-align: center; padding: 2rem; font-size: 1.2rem; }
.error { color: red; text-align: center; padding: 2rem; }
</style>
</head>
<body>
<h1 style="text-align:center; padding:1rem">المنتجات</h1>
<div id="app" class="products">
<div class="loading">جاري التحميل...</div>
</div>
<script>
async function loadProducts() {
const app = document.getElementById('app');
try {
const response = await fetch('https://fakestoreapi.com/products?limit=8');
const products = await response.json();
app.innerHTML = products.map(product => `
<div class="product">
<img src="${product.image}" alt="${product.title}">
<h3>${product.title.substring(0, 40)}...</h3>
<p class="price">${product.price} $</p>
<p>التقييم: ${product.rating.rate} ⭐ (${product.rating.count} تقييم)</p>
</div>
`).join('');
} catch (error) {
app.innerHTML = `<div class="error">فشل تحميل المنتجات: ${error.message}</div>`;
}
}
loadProducts();
</script>
</body>
</html>
التعامل مع التوثيق (Authentication)
// API Key في الهيدر
const response = await fetch('https://api.example.com/data', {
headers: {
'Authorization': 'Bearer YOUR_API_TOKEN',
'Content-Type': 'application/json'
}
});
// إنشاء دالة مساعدة لكل الطلبات
class ApiClient {
constructor(baseURL, token) {
this.baseURL = baseURL;
this.token = token;
}
async request(endpoint, options = {}) {
const url = `${this.baseURL}${endpoint}`;
const config = {
...options,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.token}`,
...options.headers
}
};
const response = await fetch(url, config);
if (!response.ok) {
throw new Error(`API Error: ${response.status}`);
}
return response.json();
}
get(endpoint) { return this.request(endpoint); }
post(endpoint, data) {
return this.request(endpoint, {
method: 'POST',
body: JSON.stringify(data)
});
}
put(endpoint, data) {
return this.request(endpoint, {
method: 'PUT',
body: JSON.stringify(data)
});
}
delete(endpoint) {
return this.request(endpoint, { method: 'DELETE' });
}
}
// الاستخدام
const api = new ApiClient('https://api.example.com', 'your-token');
const users = await api.get('/users');
const newUser = await api.post('/users', { name: "أحمد" });
أفضل الممارسات
- معالجة الأخطاء دائماً: استخدم try/catch مع كل طلب API
- إظهار حالة التحميل: أعطِ المستخدم مؤشراً أن البيانات قيد الجلب
- التخزين المؤقت: لا تجلب نفس البيانات مراراً — خزّنها محلياً
- التحقق من الاستجابة: تحقق من
response.okقبل معالجة البيانات - لا تكشف المفاتيح: لا تضع API keys في كود الواجهة الأمامية
- الأمان: استخدم HTTPS دائماً وتحقق من CORS
الخطوة التالية: ابنِ مشروعاً يستخدم API حقيقي — تطبيق طقس، أو متجر، أو لوحة تحكم — وطبّق كل المفاهيم التي تعلمتها.