הסדר חשוב
חלק מהיחידה יסודות Express במסלול ה-Node.js של Coddy. שיעור 14 מתוך 23.
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.
אתגר
קלכל תגובה מקבלת מזהה, כך שכאשר מבקר מדווח על בעיה, אפשר למצוא את הבקשה שלו ביומן. כל תגובה זקוקה למזהה: דפים, נתוני API וקבצים מתוך public.
- ב־
server.js, יש לייבא אתrandomUUIDמתוךnode:crypto. כל קריאה מחזירה מזהה אקראי חדש, כמו3b241101-e2bb-4255-8caf-4136c566a962. - יש להוסיף תווכה שמגדירה כותרת תגובה בשם
X-Request-Id, המכילהrandomUUID()חדש עבור כל בקשה, ואז קוראת ל־next(). - יש למקם אותה כך שכל בקשה תעבור דרכה, כולל הקבצים ש־
express.staticשולחת. תגובה מקבלת את הכותרת רק אם התווכה פועלת לפני שמשהו משיב.
נסו זאת: לחצו על הפעלה ושלחו את /api/recipes פעמיים. בכרטיסייה Headers, הערך של X-Request-Id שונה בכל פעם. שלחו את /style.css ואת /: גם כל אחת מהן נושאת X-Request-Id.
נסו בעצמכם
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') שולחת טקסט פשוט, כך שכל כותרת מופיעה בשורה משלה.
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');
});
כל השיעורים ביחידה יסודות Express
תרגלו בעצמכם: Express אונליין