Menu
CoddyTech

Urutan Itu Penting

Termasuk bagian Dasar-Dasar Express dalam perjalanan Node.js di Coddy. Pelajaran 14 dari 23.

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 fungsi ini harus dijalankan sebelum respons dikirim. Di sini, GET /bikes memberikan jawaban sebelum middleware tercapai, jadi responsnya tidak pernah mendapatkan header tersebut: middleware hanya melihat permintaan yang tidak dijawab oleh rute di atasnya. Middleware yang seharusnya menangani setiap respons harus diletakkan sebelum rute dan sebelum express.static.

challenge icon

Tantangan

Mudah

Setiap respons mendapat id, sehingga saat pengunjung melaporkan masalah, kamu bisa menemukan permintaan mereka di log-mu. Setiap respons membutuhkannya: halaman, data API, dan file dari public.

  1. Di server.js, impor randomUUID dari node:crypto. Setiap pemanggilan mengembalikan id acak baru, seperti 3b241101-e2bb-4255-8caf-4136c566a962.
  2. Tambahkan middleware yang menetapkan header respons bernama X-Request-Id, berisi randomUUID() baru untuk setiap permintaan, lalu memanggil next().
  3. Letakkan middleware itu agar setiap permintaan melewatinya, termasuk permintaan untuk file yang dikirim oleh express.static. Respons hanya mendapat header jika middleware berjalan sebelum ada yang memberikan respons.

Coba: Tekan Jalankan dan kirim /api/recipes dua kali. Di tab Headers, X-Request-Id memiliki nilai yang berbeda setiap kali. Kirim /style.css dan /: keduanya juga memiliki X-Request-Id.

Coba sendiri

import { escapeHtml } from './html.js';
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'));

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 muncul 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