الاستبدال باستخدام PUT
جزء من قسم واجهات REST API في رحلة Node.js على Coddy. الدرس 5 من 25.
يعيد نموذج التعديل المهمة بأكملها، بجميع حقولها دفعة واحدة. تعني PUT «استبدل المورد بهذا»، لذا يجب أن يكون المحتوى كاملاً.
PATCH /api/invoices/7 { "paid": true } → paid changes
PUT /api/invoices/7 { "amount": 90, "paid": true } → invoice 7 replaced
PUT /api/invoices/7 { "paid": true } → 400: amount missingيؤدي طلب PUT الذي ينقصه حقل إلى الاستجابة 400: فاستبدال فاتورة بنصف بياناتها سيؤدي إلى فقدان المبلغ. أما الحقول التي يديرها الخادم، مثل id ووقت الإنشاء، فتأتي من الإصدار القديم، وليس من المحتوى مطلقًا:
const { id, issuedAt } = invoices[index];
invoices[index] = { id, amount, paid, issuedAt };التحدي
سهليرسل نموذج التعديل المهمة كاملةً دفعةً واحدة. أضف مسار PUT يستبدل المهمة بما يرسله العميل.
- في
routes/tasks.js، أضفPUT /api/tasks/:id. يجب أن يحتوي جسم الطلب على كلا الحقلين، مثلًا{ "title": "Book the big room", "done": true }. - استبدل
titleوdoneللمهمة بالقيم الموجودة في جسم الطلب. احتفظ بـidوcreatedAtمن المهمة المخزنة؛ ولا تأخذهما أبدًا من جسم الطلب. أرسل الاستجابة برمز الحالة 200 والمهمة كاملةً:{ "id": 2, "title": "Book the big room", "done": true, "createdAt": "2026-03-03T10:30:00.000Z" } - إذا كان
titleأوdoneغير موجود في جسم الطلب، فأرسل الاستجابة برمز الحالة 400 و{ "error": "PUT needs every field: title and done" }، ولا تغيّر شيئًا. لا يُعد الحقل مفقودًا إلا إذا لم يكن موجودًا في جسم الطلب أصلًا:"done": falseقيمة فعلية. - إذا لم تكن هناك مهمة بهذا المعرّف، فأرسل الاستجابة برمز الحالة 404 و
{ "error": "Task not found" }، كما في المسارات الأخرى.
جرّب ذلك: يرسل PUT /api/tasks/2 مع { "title": "Book the big room", "done": true } استجابةً برمز 200 والمهمة المذكورة أعلاه. ثم إن PUT /api/tasks/2 مع { "done": true } فقط يرسل استجابةً برمز 400، ويظل GET /api/tasks/2 يعرض "Book the big room". ويرسل PUT /api/tasks/99 مع كلا الحقلين استجابةً برمز 404.
جرّب بنفسك
import { Router } from 'express';
import { nextId, tasks } from '../store.js';
const router = Router();
router.get('/', (req, res) => {
res.json(tasks);
});
router.get('/:id', (req, res) => {
const task = tasks.find((t) => t.id === Number(req.params.id));
if (!task) {
return res.status(404).json({ error: 'Task not found' });
}
res.json(task);
});
router.post('/', (req, res) => {
const { title } = req.body ?? {};
if (!title) {
return res.status(400).json({ error: 'title is required' });
}
const task = { id: nextId(), title, done: false, createdAt: new Date().toISOString() };
tasks.push(task);
res.status(201).location(`/api/tasks/${task.id}`).json(task);
});
router.patch('/:id', (req, res) => {
const task = tasks.find((t) => t.id === Number(req.params.id));
if (!task) {
return res.status(404).json({ error: 'Task not found' });
}
const { title, done } = req.body ?? {};
if (title !== undefined) task.title = title;
if (done !== undefined) task.done = done;
res.json(task);
});
router.delete('/:id', (req, res) => {
const index = tasks.findIndex((t) => t.id === Number(req.params.id));
if (index === -1) {
return res.status(404).json({ error: 'Task not found' });
}
tasks.splice(index, 1);
res.status(204).end();
});
export default router;
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس واجهات REST API
1الموارد والأفعال
الموارد وعناوين URLالإنشاء باستخدام POST4المتصفحات والإصدارات والإعدادات
ما هو المصدرالسماح لمصدر آخرCORSصفحة تستدعي APIتدرّب بنفسك: Playground لـ Express