הסדר חשוב
חלק מהיחידה יסודות Express במסלול ה-Node.js של Coddy. שיעור 12 מתוך 20.
Express מריץ תוכנות ביניים ונתיבים לפי הסדר שבו הקוד שלך מוסיף אותם, ונתיב שמחזיר תשובה מסיים את הבקשה שם.
app.get('/bikes', (req, res) => {
res.json(bikes);
});
app.use((req, res, next) => {
res.set('Cache-Control', 'no-store');
next();
});res.set(name, value) מוסיפה כותרת לתגובה, והיא חייבת לרוץ לפני שליחת התגובה. כאן GET /bikes מחזיר תשובה לפני שמגיעים לתוכנת הביניים, ולכן התגובה שלו לעולם לא מקבלת את הכותרת: תוכנת הביניים רואה רק בקשות שאף נתיב שמעליה לא החזיר להן תשובה. תוכנת ביניים שאמורה להשפיע על כל תגובה צריכה להופיע מעל הנתיבים ומעל express.static.
אתגר
קלכל תגובה, כולל דפים וקבצים, נושאת כותרת X-Request-Id שמכילה randomUUID() חדש מתוך node:crypto.
שלחו GET /api/recipes פעמיים והשוו בין הכותרות, ואז שלחו GET /style.css.
נסו בעצמכם
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('<', '<')
.replaceAll('>', '>')
.replaceAll('"', '"');
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') שולחת טקסט פשוט, ולכן כל כותרת מופיעה בשורה נפרדת.
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');
});