إدارة الإصدارات
جزء من قسم واجهات 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'التحدي
سهل- ركّب موجّه المهام على
/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');
});