أول برمجية وسيطة لك
جزء من قسم أساسيات 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() عندما لا تعثر عليه.
التحدي
سهلأضف برمجية وسيطة تطبع الطريقة والمسار لكل طلب، مثل 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('<', '<')
.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');
});
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.