Menu
CoddyTech

قراءة محتوى الطلب

جزء من قسم أساسيات 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 ولا تحفظ شيئًا.

challenge icon

التحدي

سهل
  • يضيف 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('<', '&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