Menu
CoddyTech

إدارة الإصدارات

جزء من قسم واجهات REST API في رحلة Node.js على Coddy. الدرس 15 من 18.

إن تغيير بنية الإجابة يعطّل كل عميل يستخدمها بالفعل. يتيح إصدار ضمن المسار للعملاء القدامى والجدد العمل جنبًا إلى جنب: /api/v1/orders اليوم، و/api/v2/orders عندما تتغير البنية. أما المسارات التي تتغير فتُجيب بإعادة توجيه:

GET  /api/orders/5   →  308  Location: /api/v1/orders/5
POST /api/orders     →  308  Location: /api/v1/orders

يسمح 301 و302 للعملاء بإعادة إرسال طلب POST باعتباره GET، ما يؤدي إلى إسقاط المتن. يشير 308 إلى «أعِد إرسال الطلب نفسه إلى ذلك المسار»، بما في ذلك الطريقة والمتن. داخل وسيط مُركّب، يكون req.url قد فقد مسار التركيب، بينما يحتفظ req.originalUrl به كاملًا:

// في app.use('/api/orders', ...) لطلب GET /api/orders/5?full=1
req.url          // '/5?full=1'
req.originalUrl  // '/api/orders/5?full=1'
challenge icon

التحدي

سهل
  • ركّب موجّه المهام على /api/v1/tasks.
  • يستجيب كل مسار قديم /api/tasks برمز 308 إلى المسار نفسه تحت /api/v1، مع تضمين سلسلة الاستعلام.
  • تحصل المهام الجديدة على Location: /api/v1/tasks/<id>.

أرسل GET /api/tasks/2، وPOST إلى /api/tasks مع { "title": "Order new chairs" }، ثم أرسل GET /api/v1/tasks/2.

جرّب بنفسك

import express from 'express';
import { sendError } from './errors.js';
import taskRoutes from './routes/tasks.js';

const BOARD_ORIGIN = 'https://board.example.com';

const app = express();
app.use(express.json());

// يسمح للصفحات على BOARD_ORIGIN باستدعاء واجهة API هذه من المتصفح.
app.use((req, res, next) => {
    res.set('Access-Control-Allow-Origin', BOARD_ORIGIN);
    res.set('Access-Control-Allow-Credentials', 'true');
    if (req.method === 'OPTIONS') {
        res.set('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE');
        res.set('Access-Control-Allow-Headers', 'Content-Type');
        return res.status(204).end();
    }
    next();
});

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

app.use('/api/tasks', taskRoutes);

// تنتهي هنا الأخطاء الواردة من المسارات. المحتوى الذي ليس JSON صالحًا هو
// خطأ العميل (400)؛ وأي خطأ آخر فهو من جانبنا (500).
app.use((err, req, res, next) => {
    if (err.type === 'entity.parse.failed') {
        return sendError(res, 400, 'invalid_json', 'The body is not valid JSON');
    }
    console.error(err);
    sendError(res, 500, 'server_error', 'Something went wrong');
});

app.listen(3000, () => {
    console.log('Task tracker API on port 3000');
});

جميع دروس واجهات REST API