Conflitti
Fa parte della sezione API REST del percorso Node.js di Coddy. Lezione 9 di 18.
Una seconda attività chiamata "Invia la fattura" rende l'elenco confuso, ma il suo corpo è valido. Questo è un 409 Conflict: la richiesta è in conflitto con ciò che è già memorizzato. Un 400 significa che è il corpo stesso a essere errato.
const taken = users.some((u) => u.name.toLowerCase() === name.toLowerCase());
if (taken) {
return sendError(res, 409, 'conflict', 'That username is taken');
}Confronta in minuscolo, perché le persone leggono "Ada" e "ada" come lo stesso nome. Quando una richiesta rinomina qualcosa, escludi l'elemento stesso dalla ricerca. Altrimenti, un utente che salva il modulo senza cambiare nome entra in conflitto con se stesso.
Sfida
Facile- Se un altro compito ha già un titolo, indipendentemente da maiuscole e minuscole, la risposta è 409 con il codice
conflict: con POST e con PATCH e PUT quando impostano un titolo. - Un compito può mantenere il proprio titolo.
Invia POST con { "title": "book the meeting room" }, poi PUT /api/tasks/2 con { "title": "Book the meeting room", "done": true }.
Provalo tu
import { Router } from 'express';
import { z } from 'zod';
import { sendError, sendInvalid } from '../errors.js';
import { nextId, tasks } from '../store.js';
const router = Router();
// Un'attività completa, come viene inviata da PUT. .strict() rifiuta i campi che non sono elencati.
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;