Menu
CoddyTech

Urutan Itu Penting

Termasuk bagian Dasar-Dasar Express dalam perjalanan Node.js di Coddy. Pelajaran 12 dari 20.

Express menjalankan middleware dan rute sesuai urutan penambahannya oleh kodemu, dan rute yang memberikan jawaban akan mengakhiri permintaan di sana.

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

app.use((req, res, next) => {
    res.set('Cache-Control', 'no-store');
    next();
});

res.set(name, value) menambahkan header ke respons, dan middleware harus dijalankan sebelum respons dikirim. Di sini, GET /bikes memberikan jawaban sebelum middleware tercapai, jadi responsnya tidak pernah mendapat header tersebut: middleware hanya melihat permintaan yang tidak dijawab oleh rute di atasnya. Middleware yang harus menangani setiap respons diletakkan di atas rute dan di atas express.static.

challenge icon

Tantangan

Mudah

Setiap respons, termasuk halaman dan file, membawa header X-Request-Id yang berisi randomUUID() baru dari node:crypto.

Kirim GET /api/recipes dua kali dan bandingkan header-nya, lalu kirim GET /style.css.

Coba sendiri

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

const app = express();

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

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

const escapeHtml = (text) =>
    text
        .replaceAll('&', '&')
        .replaceAll('<', '&lt;')
        .replaceAll('>', '&gt;')
        .replaceAll('"', '&quot;');

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') mengirim teks biasa, sehingga setiap judul tampil di barisnya sendiri.
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');
});

Semua pelajaran di Dasar-Dasar Express

Latihan sendiri: Playground Express