Konflik
Termasuk bagian REST API dalam perjalanan Node.js di Coddy. Pelajaran 9 dari 18.
Tugas kedua bernama "Send the invoice" membuat daftar membingungkan, tetapi isinya valid. Itu adalah 409 Conflict: permintaan bertentangan dengan yang sudah tersimpan. Kode 400 berarti isi permintaannya sendiri salah.
const taken = users.some((u) => u.name.toLowerCase() === name.toLowerCase());
if (taken) {
return sendError(res, 409, 'conflict', 'That username is taken');
}Bandingkan dalam huruf kecil, karena orang membaca "Ada" dan "ada" sebagai nama yang sama. Saat permintaan mengganti nama sesuatu, lewati item itu sendiri dalam pencarian. Jika tidak, pengguna yang menyimpan formulir tanpa mengubah namanya akan mengalami konflik dengan dirinya sendiri.
Tantangan
Mudah- Judul yang sudah dimiliki tugas lain, tanpa membedakan huruf besar dan kecil, menghasilkan respons 409 dengan kode
conflict: pada POST, serta pada PATCH dan PUT saat menetapkan judul. - Tugas boleh tetap menggunakan judulnya sendiri.
Kirim POST dengan { "title": "book the meeting room" }, lalu PUT /api/tasks/2 dengan { "title": "Book the meeting room", "done": true }.
Coba sendiri
import { Router } from 'express';
import { z } from 'zod';
import { sendError, sendInvalid } from '../errors.js';
import { nextId, tasks } from '../store.js';
const router = Router();
// Task lengkap, seperti yang dikirim oleh PUT. .strict() menolak field yang tidak tercantum di dalamnya.
const Task = z
.object({
title: z.string().trim().min(1).max(100),
done: z.boolean(),
})
.strict();
const NewTask = Task.partial({ done: true });
const TaskChanges = Task.partial();
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 sendError(res, 404, 'not_found', 'Task not found');
}
res.json(task);
});
router.post('/', (req, res) => {
const result = NewTask.safeParse(req.body);
if (!result.success) {
return sendInvalid(res, result.error);
}
const { title, done = false } = result.data;
const task = { id: nextId(), title, done, 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 sendError(res, 404, 'not_found', 'Task not found');
}
const result = TaskChanges.safeParse(req.body);
if (!result.success) {
return sendInvalid(res, result.error);
}
Object.assign(task, result.data);
res.json(task);
});
router.put('/:id', (req, res) => {
const index = tasks.findIndex((t) => t.id === Number(req.params.id));
if (index === -1) {
return sendError(res, 404, 'not_found', 'Task not found');
}
const result = Task.safeParse(req.body);
if (!result.success) {
return sendInvalid(res, result.error);
}
const { id, createdAt } = tasks[index];
tasks[index] = { id, ...result.data, createdAt };
res.json(tasks[index]);
});
router.delete('/:id', (req, res) => {
const index = tasks.findIndex((t) => t.id === Number(req.params.id));
if (index === -1) {
return sendError(res, 404, 'not_found', 'Task not found');
}
tasks.splice(index, 1);
res.status(204).end();
});
export default router;
Semua pelajaran di REST API
1Sumber Daya dan Kata Kerja
Sumber Daya dan URLMembuat dengan POSTLatihan sendiri: Playground Express