Menu
CoddyTech

أول برمجية وسيطة لك

جزء من قسم أساسيات Express في رحلة Node.js على Coddy. الدرس 11 من 20.

بعض الأعمال مطلوبة في كل طلب، مثل كتابة سطر في السجل، ونسخه إلى كل مسار لن ينتهي أبدًا.

let visits = 0;

app.use((req, res, next) => {
    visits++;
    next();
});

الدالة التي تُمرَّر إلى app.use تُسمّى برمجية وسيطة: يشغّلها Express مع كل طلب، حسب ترتيب إضافتها، قبل المسارات التي تليها. وتتلقى وسيطًا ثالثًا هو next. يؤدي استدعاء next() إلى تمرير الطلب إلى ما يأتي بعد ذلك. أما البرمجية الوسيطة التي لا تستجيب ولا تستدعي next()، فتُبقي الطلب معلّقًا إلى الأبد.

express.static من الفصل السابق هي أيضًا برمجية وسيطة: تستجيب عندما تعثر على ملف، وتستدعي next() عندما لا تعثر عليه.

challenge icon

التحدي

سهل

أضف برمجية وسيطة تطبع الطريقة والمسار لكل طلب، مثل GET /recipes/2.

أرسل GET /recipes/2 وGET /nope، ثم اقرأ وحدة التحكم.

جرّب بنفسك

import express from 'express';
import { recipes } from './data.js';

const app = express();

app.use(express.static('public'));

const escapeHtml = (text) =>
    text
        .replaceAll('&', '&')
        .replaceAll('<', '&lt;')
        .replaceAll('>', '&gt;')
        .replaceAll('"', '&quot;');

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