Menu
CoddyTech

Validando a entrada

Parte da seção APIs REST do Journey de Node.js da Coddy. Lição 6 de 25.

Um cliente pode enviar qualquer coisa no corpo, e if (!name) só impede os valores vazios. 123, true e ["x"] são truthy e passam pela verificação. Uma string com espaços também passa: detecte-a com trim(), já que ' '.trim() é ''. Verifique o tipo de cada campo com typeof e, em seguida, seus 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' });
}

Escreva a mensagem para quem lê a resposta: indique o campo e diga o que ele deve ser, para que a pessoa saiba o que corrigir. Uma requisição PATCH verifica apenas os campos enviados, pois os outros não estão sendo alterados.

challenge icon

Desafio

Fácil

No momento, if (!title) deixa passar títulos como 123 ou " ". Verifique o tipo e o tamanho de cada campo antes de salvá-lo.

  1. Em routes/tasks.js, na rota POST, verifique title:
    • Precisa ser uma string.
    • Não pode estar vazio nem conter apenas espaços.
    • Precisa ter no máximo 100 caracteres, incluindo espaços.

    Se qualquer uma dessas condições não for atendida, responda com o status 400 e uma mensagem de error que contenha a palavra title, por exemplo:

    { "error": "title must be a string of 1 to 100 characters" }
  2. Na rota PATCH, verifique apenas os campos enviados no corpo da requisição:
    • Se ele enviar title, aplique a mesma regra e o mesmo tipo de erro.
    • Se ele enviar done, o valor precisa ser true ou false. Caso contrário, responda com o status 400 e um erro que contenha a palavra done:
    { "error": "done must be true or false" }
    Uma requisição PATCH recusada não altera nada.
  3. Corpos válidos continuam funcionando: POST ainda retorna 201, e PATCH com { "done": true } ainda retorna 200. Deixe PUT como está; o Schemas também verifica isso com zod.

Experimente: envie POST com { "title": 123 } para /api/tasks: você recebe 400 com o erro de title. Envie POST com { "title": " " }: também recebe 400. PATCH /api/tasks/2 com { "done": "yes" }: recebe 400 com o erro de done, e GET /api/tasks/2 ainda mostra "done": false. PATCH /api/tasks/2 com { "done": true }: recebe 200.

Experimente você mesmo

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 iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de APIs REST

Pratique por conta própria: Playground de Express