Menu
CoddyTech

Dein erstes Middleware

Teil des Abschnitts Express-Grundlagen der Node.js-Journey von Coddy. Lektion 13 von 23.

Manche Aufgaben fallen bei jeder Anfrage an, etwa eine Zeile ins Protokoll zu schreiben, und sie in jede Route zu kopieren, würde nie enden. Jede Anfrage hat eine Methode in req.method: GET, um etwas abzurufen, POST, um etwas zu senden.

let visits = 0;

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

Eine Funktion, die an app.use übergeben wird, ist Middleware: Express führt sie bei jeder Anfrage und in der Reihenfolge aus, in der sie hinzugefügt wurde, bevor die darunterstehenden Routen ausgeführt werden. Sie erhält ein drittes Argument, next. Durch den Aufruf von next() wird die Anfrage an das weitergegeben, was als Nächstes kommt. Eine Middleware, die weder antwortet noch next() aufruft, lässt die Anfrage für immer warten.

express.static aus dem letzten Kapitel ist ebenfalls Middleware: Sie antwortet, wenn sie eine Datei findet, und ruft next() auf, wenn sie keine findet.

challenge icon

Aufgabe

Einfach

Du möchtest für jede Anfrage, die dein Server erhält, eine Protokollzeile, damit du sehen kannst, wonach Besucher fragen.

  1. Füge in server.js direkt nach const app = express(); eine Middleware mit app.use hinzu. Dort platziert, wird sie vor jeder Route ausgeführt.
  2. Für jede Anfrage gibt sie eine Zeile in der Konsole aus: die Methode der Anfrage, ein Leerzeichen und anschließend ihren Pfad. Eine Anfrage an /recipes/2 gibt GET /recipes/2 aus. Die Methode steht in req.method (GET, POST und so weiter) und der Pfad in req.url.
  3. Nach der Ausgabe ruft sie next() auf, damit die Anfrage zu den Routen weitergeleitet wird.

Probier es aus: Drücke auf „Spielen“ und sende /recipes/2. Du solltest Pancakes sehen, und in der Konsole wird GET /recipes/2 angezeigt. Sende /api/recipes: Die Liste wie gewohnt und GET /api/recipes in der Konsole. Sende /nope: eine 404, und in der Konsole wird weiterhin GET /nope angezeigt, weil die Middleware ausgeführt wird, bevor Express nach einer Route sucht.

Probier es selbst

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') sendet unformatierten Text, sodass jeder Titel in einer eigenen Zeile erscheint.
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 dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Express-Grundlagen

Übe selbstständig: Express-Playground