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.
Tantangan
MudahSetiap 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.
- Di
server.js, imporrandomUUIDdarinode:crypto. Setiap pemanggilan mengembalikan id acak baru, seperti3b241101-e2bb-4255-8caf-4136c566a962. - Tambahkan middleware yang menetapkan header respons bernama
X-Request-Id, berisirandomUUID()baru untuk setiap permintaan, lalu memanggilnext(). - 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