ה-Middleware הראשון שלך
חלק מהיחידה יסודות Express במסלול ה-Node.js של Coddy. שיעור 13 מתוך 23.
יש עבודה ששייכת לכל בקשה, כמו כתיבת שורה ליומן, והעתקה שלה לכל נתיב לא תסתיים לעולם. לכל בקשה יש שיטה, ב־req.method: GET כדי להביא משהו, POST כדי לשלוח משהו.
let visits = 0;
app.use((req, res, next) => {
visits++;
next();
});פונקציה שמועברת אל app.use היא תוכנת ביניים: Express מריץ אותה עבור כל בקשה, לפי הסדר שבו היא נוספה, לפני הנתיבים שמתחתיה. היא מקבלת ארגומנט שלישי, next. קריאה ל־next() מעבירה את הבקשה הלאה, אל הדבר הבא. תוכנת ביניים שלא משיבה וגם לא קוראת ל־next() משאירה את הבקשה בהמתנה לנצח.
גם express.static מהפרק הקודם היא תוכנת ביניים: היא משיבה כשהיא מוצאת קובץ וקוראת ל־next() כשהיא לא מוצאת אותו.
אתגר
קלאתה רוצה שורת יומן עבור כל בקשה שהשרת שלך מקבל, כדי שתוכל לראות מה המבקרים מבקשים.
- ב־
server.js, מיד אחריconst app = express();, הוסף תוכנת ביניים באמצעותapp.use. כשהיא ממוקמת שם, היא פועלת לפני כל נתיב. - עבור כל בקשה, היא מדפיסה שורה אחת למסוף: את שיטת הבקשה, רווח, ואז את הנתיב שלה. בקשה אל
/recipes/2מדפיסהGET /recipes/2. השיטה נמצאת ב־req.method(GET,POSTוכן הלאה), והנתיב נמצא ב־req.url. - אחרי ההדפסה, היא קוראת ל־
next(), כך שהבקשה ממשיכה לנתיבים.
נסה זאת: לחץ על „שחק” ושלח את /recipes/2. אתה אמור לראות את Pancakes, ובמסוף מופיע GET /recipes/2. שלח את /api/recipes: הרשימה כרגיל, ובמסוף GET /api/recipes. שלח את /nope: מתקבלת שגיאת 404, ובמסוף עדיין מופיע GET /nope, כי תוכנת הביניים פועלת לפני ש־Express מחפש נתיב.
נסו בעצמכם
import { escapeHtml } from './html.js';
import express from 'express';
import { recipes } from './data.js';
const app = express();
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 אונליין