إدارة الإصدارات
جزء من قسم واجهات REST API في رحلة Node.js على Coddy. الدرس 22 من 25.
يؤدي تغيير شكل الاستجابة إلى تعطيل كل عميل يستخدمها بالفعل. يتيح وضع الإصدار في المسار للعميلين القديم والجديد العمل جنبًا إلى جنب: /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 بطرق لا تتوقعها العملاء القديمة، لذا أضف رقم إصدار إلى مساراتها. تصبح واجهة API الحالية الإصدار 1، على /api/v1/tasks، وتُوجّه العناوين القديمة العملاء إليها.
- في
server.js، اربط موجّه المهام بالمسار/api/v1/tasksبدلًا من/api/tasks. - أضف أيضًا في
server.jsبرمجية وسيطة مرتبطة بالمسار/api/tasksلا تقوم إلا بإعادة التوجيه. تستجيب برمز الحالة 308 إلى العنوان نفسه ضمن/api/v1، مع الإبقاء على بقية المسار وسلسلة الاستعلام. داخل برمجية وسيطة مرتبطة بمسار، يحتويreq.originalUrlعلى العنوان القديم كاملًا. على سبيل المثال:- تُعيد
GET /api/tasks/2التوجيه إلى/api/v1/tasks/2. - تُعيد
POST /api/tasksالتوجيه إلى/api/v1/tasks. - تُعيد
GET /api/tasks?done=false&sort=titleالتوجيه إلى/api/v1/tasks?done=false&sort=title.
استخدم 308، لا 301: بعد استجابة 308، يعيد العميل إرسال طلب POST على هيئة POST، مع تضمين جسم الطلب.
- تُعيد
- في
routes/tasks.js، يضبط مسار POST قيمةLocationعلى العنوان الجديد، مثل/api/v1/tasks/4للمهمة 4.
جرّب ذلك: يُرجع GET /api/tasks/2 الرمز 308، وتُظهر علامة التبويب Headers القيمة Location: /api/v1/tasks/2. يعرض شريط الطلب إعادة التوجيه نفسها؛ ولا يتبعها. أرسل POST مع الجسم { "title": "Order new chairs" } إلى /api/tasks: ستحصل على 308 مع Location: /api/v1/tasks، ولن تُنشأ أي مهمة. أرسل POST بالجسم نفسه إلى /api/v1/tasks: ستحصل على 201 مع Location: /api/v1/tasks/4. يُرجع GET /api/v1/tasks/2 المهمة 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();
// يسمح للصفحات على BOARD_ORIGIN باستدعاء واجهة API هذه من المتصفح.
app.use((req, res, next) => {
res.set('Access-Control-Allow-Origin', BOARD_ORIGIN);
if (req.method === 'OPTIONS') {
res.set('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS');
res.set('Access-Control-Allow-Headers', 'Content-Type');
return res.status(204).end();
}
next();
});
app.use(express.json());
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
1الموارد والأفعال
الموارد وعناوين URLالإنشاء باستخدام POST4المتصفحات والإصدارات والإعدادات
ما هو المصدرالسماح لمصدر آخرCORSصفحة تستدعي APIتدرّب بنفسك: Playground لـ Express