Menu
CoddyTech

Rezept des Tages

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

Recipe Box kann vertraute Kenntnisse zu Routen und zum Lesen von Dateien nutzen, um für einen Tag ein Rezept bereitzustellen. Der bereitgestellte Helfer dayOfYear wandelt ein Datum in eine Zahl um: Der 1. Januar ist 1 und der 1. März 2026 ist 60. Ein fehlendes Datum bedeutet heute; nicht lesbarer Text gibt null zurück.

const day = dayOfYear(req.query.date);
// ?date=2026-03-01 ergibt 60
// ?date=soon ergibt null

Verwende den Restwertoperator, um eine Position auszuwählen: day % recipes.length. Bei vier Rezepten wählt der Tag 60 die Position null aus. Lade die Rezepte innerhalb der Anfrage, damit auch kürzlich veröffentlichte Rezepte berücksichtigt werden. Die Datumsanalyse ist bereits bereitgestellt; konzentriere dich darauf, die Route zusammenzusetzen.

challenge icon

Aufgabe

Einfach

Füge Recipe Box einen Endpunkt für das Rezept des Tages hinzu. Die bereitgestellte Datei day-of-year.js exportiert dayOfYear(text), das die Tagesnummer oder bei einem ungültigen Datum null zurückgibt.

  1. Exportiere loadRecipes aus routes/recipes.js. Importiere es in server.js: Der Router bleibt der Standardimport, und { loadRecipes } folgt darauf nach einem Komma.
  2. Importiere dayOfYear. Füge in server.js oberhalb des 404-Handlers eine async-Route für GET /api/today hinzu. Übergib req.query.date an die Hilfsfunktion.
  3. Gib bei null den Statuscode 400 mit {"error":"Use a date like 2026-03-01"} zurück.
  4. Rufe andernfalls loadRecipes() mit await auf und gib recipes[day % recipes.length] als JSON zurück. Behalte die vorhandenen Routen und den Fehler-Handler bei.

Probiere GET /api/today?date=2026-03-01 aus: Der erste Eintrag wird zurückgegeben, weil die Tagesnummer 60 beträgt und es vier Rezepte gibt. Probiere ?date=soon aus: Der oben angegebene 400-Fehler wird zurückgegeben.

Probier es selbst

import { escapeHtml } from './html.js';
import express from 'express';
import { randomUUID } from 'node:crypto';
import { recipes } from './data.js';
import recipesRouter from './routes/recipes.js';
import reviewsRouter from './routes/reviews.js';

const app = express();

app.use((req, res, next) => {
    console.log(`${req.method} ${req.url}`);
    next();
});

app.use((req, res, next) => {
    res.set('X-Request-Id', randomUUID());
    next();
});

app.use(express.json());

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 reinen 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.use('/api/recipes', recipesRouter);
app.use('/api/recipes/:id/reviews', reviewsRouter);

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.use((req, res) => {
    if (req.path.startsWith('/api/')) {
        res.status(404).json({ error: 'Not found' });
        return;
    }
    res.status(404).send('<h1>Page not found</h1><p><a href="/">Back to Recipe Box</a></p>');
});

app.use((err, req, res, next) => {
    console.error(err);
    res.status(500).json({ error: 'Something went wrong' });
});

app.listen(3000, () => {
    console.log('Recipe Box is running on port 3000');
});

Alle Lektionen in Express-Grundlagen

Übe selbstständig: Express-Playground