قراءة محتوى الطلب
جزء من قسم أساسيات Express في رحلة Node.js على Coddy. الدرس 13 من 20.
يرسل طلب POST البيانات في متنه، ولا يقرأ Express المتن ما لم تطلب منه ذلك.
app.use(express.json());
app.post('/api/loans', (req, res) => {
const { bookId, member } = req.body;
res.status(201).json({ bookId, member, due: '2026-11-08' });
});يطلب GET شيئًا ما؛ أما POST فيرسل شيئًا ليتم إنشاؤه. إن express.json() برمجية وسيطة تقرأ كل متن JSON إلى req.body. من دونها تكون قيمة req.body هي undefined. ويجيب المسار الذي ينشئ شيئًا ما برمز الحالة 201 مع ما أنشأه.
تحقق من المتن قبل حفظه. الحقل المفقود خطأ من العميل، لذا أجب برمز الحالة 400 ولا تحفظ شيئًا.
التحدي
سهل- يضيف
POST /api/recipesوصفةً بمعرّف جديد باستخدام{ "title", "tags" }، ويستجيب بالوصفة مع201. - من دون
title: يستجيب بالرمز400مع{ "error": "A recipe needs a title" }.
أرسل طلب POST مع متن، ثم GET /api/recipes، ثم طلب POST من دون عنوان.
جرّب بنفسك
import express from 'express';
import { randomUUID } from 'node:crypto';
import { recipes } from './data.js';
const app = express();
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`);
next();
});
app.use((req, res, next) => {
res.set('X-Request-Id', randomUUID());
next();
});
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');
});
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.