حجم الخط:
|
Getting your Trinity Audio player ready...
|
“`html
APIs: الدليل الشامل لبناء واستهلاك REST و GraphQL APIs مع أمثلة كود عملية في 2026
مقتطف المقال:
APIs (Application Programming Interfaces) هي العمود الفقري للتطبيقات الحديثة. بدونها، لا يمكن للتطبيقات التواصل مع بعضها البعض. في هذا الدليل الشامل، ستتعلم كل شيء عن APIs: من REST الأشهر، إلى GraphQL الأحدث، كيفية بناء API احترافي، كيفية استهلاكه، المصادقة والأمان، مع أمثلة كود عملية باستخدام Node.js و Express.
APIs (Application Programming Interfaces) هي العمود الفقري للتطبيقات الحديثة. بدونها، لا يمكن للتطبيقات التواصل مع بعضها البعض. في هذا الدليل الشامل، ستتعلم كل شيء عن APIs: من REST الأشهر، إلى GraphQL الأحدث، كيفية بناء API احترافي، كيفية استهلاكه، المصادقة والأمان، مع أمثلة كود عملية باستخدام Node.js و Express.
ما هي APIs ولماذا مهمة؟
API (Application Programming Interface) هو مجموعة من القواعد والبروتوكولات التي تسمح للتطبيقات بالتواصل مع بعضها البعض. هو الوسيط الذي يسمح لتطبيقين مختلفين بالتحدث مع بعضهما.
🔌 التكامل: ربط التطبيقات ببعضها
⚡ الكفاءة: إعادة استخدام الكود
🔒 الأمان: التحكم في الوصول
🌐 التوسع: بناء أنظمة قابلة للتوسع
💡 أمثلة على استخدام APIs في الحياة اليومية
- خرائط جوجل: تطبيقات تستخدم API خرائط جوجل
- الدفع الإلكتروني: Stripe, PayPal APIs
- وسائل التواصل: Facebook, Twitter APIs
- الطقس: Weather APIs
- البريد الإلكتروني: SendGrid, Mailgun APIs
أنواع APIs
⚖️ مقارنة شاملة: REST vs GraphQL vs SOAP
REST API: الأشهر والأكثر استخداماً
🌐 ما هو REST API؟
REST (Representational State Transfer) هو نمط معماري لبناء APIs. يستخدم بروتوكول HTTP ويعتمد على الموارد (Resources) والعمليات (Operations).
مبادئ REST:
- Client-Server: فصل الواجهة عن الخادم
- Stateless: كل طلب مستقل
- Cacheable: الاستجابات قابلة للتخزين المؤقت
- Uniform Interface: واجهة موحدة
- Layered System: نظام طبقي
🌐 HTTP Methods في REST
بناء REST API مع Node.js و Express
🛠️ إعداد المشروع
# إنشاء المشروع mkdir my-api cd my-api npm init -y # تثبيت المكتبات npm install express mongoose cors dotenv bcryptjs jsonwebtoken npm install --save-dev nodemon # هيكل المشروع my-api/ ├── src/ │ ├── controllers/ │ ├── models/ │ ├── routes/ │ ├── middleware/ │ ├── config/ │ └── app.js ├── .env ├── package.json └── server.js
🛠️ بناء API كامل
// server.js const express = require('express'); const cors = require('cors'); const mongoose = require('mongoose'); require('dotenv').config(); const app = express(); // Middleware app.use(cors()); app.use(express.json()); // Connect to MongoDB mongoose.connect(process.env.MONGODB_URI) .then(() => console.log('MongoDB connected')) .catch(err => console.error(err)); // Routes app.use('/api/users', require('./routes/users')); app.use('/api/products', require('./routes/products')); // Error handling app.use((err, req, res, next) => { res.status(err.status || 500).json({ error: err.message || 'Internal Server Error' }); }); const PORT = process.env.PORT || 5000; app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
🛠️ Model (User Model)
// models/User.js const mongoose = require('mongoose'); const bcrypt = require('bcryptjs'); const userSchema = new mongoose.Schema({ name: { type: String, required: [true, 'Name is required'], trim: true }, email: { type: String, required: [true, 'Email is required'], unique: true, lowercase: true }, password: { type: String, required: [true, 'Password is required'], minlength: 6 }, role: { type: String, enum: ['user', 'admin'], default: 'user' } }, { timestamps: true }); // Hash password before saving userSchema.pre('save', async function(next) { if (!this.isModified('password')) return next(); this.password = await bcrypt.hash(this.password, 10); next(); }); // Compare password method userSchema.methods.comparePassword = async function(candidatePassword) { return await bcrypt.compare(candidatePassword, this.password); }; module.exports = mongoose.model('User', userSchema);
🛠️ Controller (Users Controller)
// controllers/usersController.js const User = require('../models/User'); const jwt = require('jsonwebtoken'); // @desc Register user // @route POST /api/users/register exports.register = async (req, res) => { try { const { name, email, password } = req.body; // Check if user exists const existingUser = await User.findOne({ email }); if (existingUser) { return res.status(400).json({ error: 'User already exists' }); } // Create user const user = await User.create({ name, email, password }); // Generate token const token = jwt.sign( { id: user._id }, process.env.JWT_SECRET, { expiresIn: '30d' } ); res.status(201).json({ success: true, token, user: { id: user._id, name: user.name, email: user.email } }); } catch (error) { res.status(500).json({ error: error.message }); } }; // @desc Login user // @route POST /api/users/login exports.login = async (req, res) => { try { const { email, password } = req.body; // Find user const user = await User.findOne({ email }).select('+password'); if (!user) { return res.status(401).json({ error: 'Invalid credentials' }); } // Check password const isMatch = await user.comparePassword(password); if (!isMatch) { return res.status(401).json({ error: 'Invalid credentials' }); } // Generate token const token = jwt.sign( { id: user._id }, process.env.JWT_SECRET, { expiresIn: '30d' } ); res.json({ success: true, token, user: { id: user._id, name: user.name, email: user.email } }); } catch (error) { res.status(500).json({ error: error.message }); } }; // @desc Get all users // @route GET /api/users exports.getUsers = async (req, res) => { try { const users = await User.find(); res.json({ success: true, data: users }); } catch (error) { res.status(500).json({ error: error.message }); } }; // @desc Get user by ID // @route GET /api/users/:id exports.getUser = async (req, res) => { try { const user = await User.findById(req.params.id); if (!user) { return res.status(404).json({ error: 'User not found' }); } res.json({ success: true, data: user }); } catch (error) { res.status(500).json({ error: error.message }); } }; // @desc Update user // @route PUT /api/users/:id exports.updateUser = async (req, res) => { try { const user = await User.findByIdAndUpdate( req.params.id, req.body, { new: true, runValidators: true } ); if (!user) { return res.status(404).json({ error: 'User not found' }); } res.json({ success: true, data: user }); } catch (error) { res.status(500).json({ error: error.message }); } }; // @desc Delete user // @route DELETE /api/users/:id exports.deleteUser = async (req, res) => { try { const user = await User.findByIdAndDelete(req.params.id); if (!user) { return res.status(404).json({ error: 'User not found' }); } res.json({ success: true, data: {} }); } catch (error) { res.status(500).json({ error: error.message }); } };
🛠️ Routes
// routes/users.js const express = require('express'); const router = express.Router(); const { protect } = require('../middleware/auth'); const { register, login, getUsers, getUser, updateUser, deleteUser } = require('../controllers/usersController'); router.post('/register', register); router.post('/login', login); router.get('/', protect, getUsers); router.get('/:id', protect, getUser); router.put('/:id', protect, updateUser); router.delete('/:id', protect, deleteUser); module.exports = router;
🛠️ Auth Middleware
// middleware/auth.js const jwt = require('jsonwebtoken'); const User = require('../models/User'); exports.protect = async (req, res, next) => { let token; // Check for token if (req.headers.authorization && req.headers.authorization.startsWith('Bearer')) { token = req.headers.authorization.split(' ')[1]; } if (!token) { return res.status(401).json({ error: 'Not authorized' }); } try { // Verify token const decoded = jwt.verify(token, process.env.JWT_SECRET); // Get user req.user = await User.findById(decoded.id); next(); } catch (error) { res.status(401).json({ error: 'Not authorized' }); } };
استهلاك API من Frontend
🌐 استهلاك API مع Fetch API
// Register User const registerUser = async (name, email, password) => { try { const response = await fetch('http://localhost:5000/api/users/register', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name, email, password }) }); const data = await response.json(); if (!response.ok) { throw new Error(data.error); } // Store token localStorage.setItem('token', data.token); return data; } catch (error) { console.error('Error:', error); } }; // Login User const loginUser = async (email, password) => { try { const response = await fetch('http://localhost:5000/api/users/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }) }); const data = await response.json(); if (!response.ok) { throw new Error(data.error); } localStorage.setItem('token', data.token); return data; } catch (error) { console.error('Error:', error); } }; // Get Users (Protected) const getUsers = async () => { try { const token = localStorage.getItem('token'); const response = await fetch('http://localhost:5000/api/users', { headers: { 'Authorization': `Bearer ${token}` } }); const data = await response.json(); return data; } catch (error) { console.error('Error:', error); } };
🌐 استهلاك API مع Axios
// Install Axios npm install axios // Create Axios instance import axios from 'axios'; const api = axios.create({ baseURL: 'http://localhost:5000/api', headers: { 'Content-Type': 'application/json' } }); // Add token interceptor api.interceptors.request.use( (config) => { const token = localStorage.getItem('token'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }, (error) => { return Promise.reject(error); } ); // API calls export const registerUser = (data) => api.post('/users/register', data); export const loginUser = (data) => api.post('/users/login', data); export const getUsers = () => api.get('/users'); export const getUser = (id) => api.get(`/users/${id}`); export const updateUser = (id, data) => api.put(`/users/${id}`, data); export const deleteUser = (id) => api.delete(`/users/${id}`); // Usage in React component import { getUsers } from './api'; function UsersList() { const [users, setUsers] = useState([]); useEffect(() => { fetchUsers(); }, []); const fetchUsers = async () => { try { const response = await getUsers(); setUsers(response.data.data); } catch (error) { console.error(error); } }; return ( <div> {users.map(user => ( <div key={user.id}>{user.name}</div> ))} </div> ); }
GraphQL: البديل الحديث
🌐 ما هو GraphQL؟
GraphQL هي لغة استعلام للـ APIs طورتها Facebook. تسمح للعميل بطلب بالضبط ما يحتاجه، لا أكثر ولا أقل.
مميزات GraphQL:
- Ask for what you need: لا over-fetching أو under-fetching
- Get what you ask: تحصل بالضبط على ما طلبت
- Single endpoint: endpoint واحد لكل العمليات
- Strong typing: نظام أنواع قوي
- Introspection: يمكن الاستعلام عن الـ API نفسه
🌐 بناء GraphQL API
# Install dependencies
npm install @apollo/server graphql @apollo/server-plugins



