Menu
CoddyTech

Valider les entrées

Fait partie de la section API REST du Journey Node.js de Coddy. Leçon 6 sur 25.

Un client peut envoyer n’importe quoi dans un corps de requête, et if (!name) ne bloque que les valeurs vides. 123, true et ["x"] sont des valeurs truthy et passent. Une chaîne composée d’espaces passe aussi : détectez-la avec trim(), puisque ' '.trim() donne ''. Vérifiez le type de chaque champ avec typeof, puis ses limites :

const { seats } = req.body ?? {};
if (typeof seats !== 'number' || !Number.isInteger(seats) || seats < 1) {
    return res.status(400).json({ error: 'seats must be a whole number from 1' });
}

Rédigez le message à l’intention de la personne qui lit la réponse : nommez le champ et indiquez ce qu’il doit être, afin qu’elle sache quoi corriger. Une requête PATCH vérifie uniquement les champs qui lui ont été envoyés, puisque les autres ne changent pas.

challenge icon

Défi

Facile

Actuellement, if (!title) laisse passer un titre comme 123 ou " ". Vérifie le type et la taille de chaque champ avant de l’enregistrer.

  1. Dans routes/tasks.js, dans la route POST, vérifie title :
    • Il doit s’agir d’une chaîne de caractères.
    • Elle ne doit pas être vide ni contenir uniquement des espaces.
    • Elle doit comporter au maximum 100 caractères, espaces compris.

    Si l’une de ces conditions n’est pas remplie, renvoie le statut 400 et un message d’erreur qui contient le mot title, par exemple :

    { "error": "title must be a string of 1 to 100 characters" }
  2. Dans la route PATCH, vérifie uniquement les champs envoyés dans le corps de la requête :
    • S’il envoie title, la même règle s’applique, ainsi que le même type de message d’erreur.
    • S’il envoie done, sa valeur doit être true ou false. Sinon, renvoie le statut 400 et une erreur qui contient le mot done :
    { "error": "done must be true or false" }
    Un PATCH refusé ne modifie rien.
  3. Les corps de requête valides continuent de fonctionner : POST renvoie toujours 201, et un PATCH avec { "done": true } renvoie toujours 200. Laisse PUT tel quel ; Schemas le vérifie aussi avec zod.

Essaie : envoie POST { "title": 123 } à /api/tasks : tu obtiens 400 avec l’erreur concernant title. Envoie POST { "title": " " } : tu obtiens aussi 400. Envoie PATCH /api/tasks/2 avec { "done": "yes" } : tu obtiens 400 avec l’erreur concernant done, et GET /api/tasks/2 affiche toujours "done": false. Envoie PATCH /api/tasks/2 avec { "done": true } : tu obtiens 200.

Essayez vous-même

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.put('/: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' });
    }
    const { title, done } = req.body ?? {};
    if (title === undefined || done === undefined) {
        return res.status(400).json({ error: 'PUT needs every field: title and done' });
    }
    const { id, createdAt } = tasks[index];
    tasks[index] = { id, title, done, 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 res.status(404).json({ error: 'Task not found' });
    }
    tasks.splice(index, 1);
    res.status(204).end();
});

export default router;
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de API REST

Entraînez-vous par vous-même : Playground Express