Konflik
Termasuk bagian REST API dalam perjalanan Node.js di Coddy. Pelajaran 13 dari 25.
Tugas kedua bernama "Kirim faktur" membuat daftar membingungkan, tetapi isinya valid. Itu adalah 409 Conflict: permintaan bertentangan dengan yang sudah tersimpan. 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 menganggap "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
MudahDua tugas bernama "Send the invoice" membuat daftar membingungkan. Tolak judul yang sudah dimiliki tugas lain.
- Di
routes/tasks.js, bandingkan judul tanpa membedakan huruf besar dan kecil: "Book the meeting room" dan "book the MEETING room" dianggap sebagai judul yang sama. - Di POST, setelah pemeriksaan skema berhasil: jika ada tugas yang sudah memiliki judul tersebut, gunakan
sendErroruntuk merespons dengan status 409, dan jangan tambahkan apa pun:{ "error": { "code": "conflict", "message": "A task with this title already exists" } } - Lakukan hal yang sama di PATCH (hanya saat body-nya mengirim
title) dan di PUT. Di kedua route ini, jangan sertakan tugas yang sedang diubah saat mencari, sehingga tugas boleh mempertahankan judulnya sendiri atau hanya mengubah huruf kapitalnya. PATCH atau PUT yang ditolak tidak mengubah apa pun.
Coba: POST { "title": "book the meeting room" } ke /api/tasks: kamu mendapat 409 dengan code conflict, karena tugas 2 bernama "Book the meeting room". PATCH /api/tasks/3 dengan { "title": "Write the Project Brief" }: 409, dan GET /api/tasks/3 tetap menampilkan "Send the invoice". PUT /api/tasks/2 dengan { "title": "Book the meeting room", "done": true }: 200, karena itu adalah judul tugas 2 sendiri. POST { "title": "Order new chairs" }: 201.
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.
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 POST4Peramban, Versi, dan Konfigurasi
Apa Itu OriginMengizinkan Origin LainCORSHalaman yang Memanggil APILatihan sendiri: Playground Express