Menu
CoddyTech

ה-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() כשהיא לא מוצאת אותו.

challenge icon

אתגר

קל

אתה רוצה שורת יומן עבור כל בקשה שהשרת שלך מקבל, כדי שתוכל לראות מה המבקרים מבקשים.

  1. ב־server.js, מיד אחרי const app = express();, הוסף תוכנת ביניים באמצעות app.use. כשהיא ממוקמת שם, היא פועלת לפני כל נתיב.
  2. עבור כל בקשה, היא מדפיסה שורה אחת למסוף: את שיטת הבקשה, רווח, ואז את הנתיב שלה. בקשה אל /recipes/2 מדפיסה GET /recipes/2. השיטה נמצאת ב־req.method (GET, POST וכן הלאה), והנתיב נמצא ב־req.url.
  3. אחרי ההדפסה, היא קוראת ל־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');
});
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה יסודות Express

תרגלו בעצמכם: Express אונליין