Menu
CoddyTech

Seu primeiro middleware

Parte da seção Fundamentos de Express do Journey de Node.js da Coddy. Lição 13 de 23.

Algumas tarefas fazem parte de toda requisição, como escrever uma linha no log, e copiá-las para cada rota nunca teria fim. Toda requisição tem um método, em req.method: GET para buscar algo, POST para enviar algo.

let visits = 0;

app.use((req, res, next) => {
    visits++;
    next();
});

Uma função passada para app.use é um middleware: o Express a executa para toda requisição, na ordem em que foi adicionado, antes das rotas abaixo dele. Ela recebe um terceiro argumento, next. Chamar next() passa a requisição adiante para o que vier a seguir. Um middleware que não responde nem chama next() deixa a requisição esperando para sempre.

express.static do capítulo anterior também é middleware: ele responde quando encontra um arquivo e chama next() quando não encontra.

challenge icon

Desafio

Fácil

Você quer uma linha de registro para cada requisição recebida pelo servidor, para ver o que os visitantes solicitam.

  1. Em server.js, logo após const app = express();, adicione um middleware com app.use. Posicionado ali, ele é executado antes de cada rota.
  2. Para cada requisição, ele imprime uma linha no Console: o método da requisição, um espaço e, em seguida, o caminho. Uma requisição para /recipes/2 imprime GET /recipes/2. O método está em req.method (GET, POST e assim por diante), e o caminho está em req.url.
  3. Depois de imprimir, ele chama next(), para que a requisição siga para as rotas.

Experimente: Pressione Executar e envie /recipes/2. Você deverá ver Pancakes, e o Console exibirá GET /recipes/2. Envie /api/recipes: a lista de sempre, e GET /api/recipes no Console. Envie /nope: uma resposta 404, e o Console ainda exibirá GET /nope, porque o middleware é executado antes de o Express procurar uma rota.

Experimente você mesmo

import { escapeHtml } from './html.js';
import express from 'express';
import { recipes } from './data.js';

const app = express();

app.use(express.static('public'));

app.get('/', (req, res) => {
    const items = recipes.map((r) => `<li><a href="/recipes/${r.id}">${escapeHtml(r.title)}</a></li>`);
    res.send(`<link rel="stylesheet" href="/style.css"><h1>Recipe Box</h1><ul>${items.join('')}</ul>`);
});

// type('text') envia texto simples, então cada título aparece em sua própria linha.
app.get('/recipes', (req, res) => {
    const { tag } = req.query;
    const list = tag ? recipes.filter((recipe) => recipe.tags.includes(tag)) : recipes;
    res.type('text').send(list.map((recipe) => recipe.title).join('\n'));
});

app.get('/recipes/:id', (req, res) => {
    const recipe = recipes.find((r) => r.id === Number(req.params.id));
    if (!recipe) {
        res.status(404).send('No such recipe');
        return;
    }
    res.send(recipe.title);
});

app.get('/api/recipes', (req, res) => {
    res.json(recipes);
});

app.get('/api/recipes/:id', (req, res) => {
    const recipe = recipes.find((r) => r.id === Number(req.params.id));
    if (!recipe) {
        res.status(404).json({ error: 'No such recipe' });
        return;
    }
    res.json(recipe);
});

app.get('/about', (req, res) => {
    res.send('Recipe Box collects family recipes.');
});

app.get('/menu', (req, res) => {
    res.redirect(301, '/recipes');
});

app.get('/menu/:id', (req, res) => {
    res.redirect(301, `/recipes/${req.params.id}`);
});

app.listen(3000, () => {
    console.log('Recipe Box is running on port 3000');
});
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 Fundamentos de Express

Pratique por conta própria: Playground de Express