يقوم مهندسان في نفس الفريق بنشر نقطتي نهاية في نفس الأسبوع. أحدهما يُرجع created_at، والآخر يُرجع createdAt. أحدهما يستخدم الترقيم بـ ?page=2، والآخر بـ ?offset=20. أحدهما يضع الأخطاء في كائن error على المستوى الأعلى، والآخر يدرج رسالة message نصية. كلاهما يمر بمراجعة الكود، لأن المراجعين يقرأون المنطق وليس التسمية. بعد ستة أشهر، تبدو واجهة برمجة التطبيقات (API) الخاصة بك وكأنها كتبت بواسطة خمس شركات مختلفة، وكل تكامل عميل يحتاج إلى حالة خاصة.
محلل OpenAPI موجود لاكتشاف هذا الانحراف قبل نشره. يقرأ وثيقة OpenAPI الخاصة بك، ويقوم بتشغيلها مقابل مجموعة من القواعد (يجب أن تحتوي العمليات على أوصاف، ويجب أن تحتوي المخططات على أمثلة، وتتبع أسماء الخصائص اصطلاح حالة، وكل استجابة تعلن عن نوع وسائط)، ويفشل البناء عند كسر إحدى القواعد. إنها نفس فكرة ESLint لـ JavaScript أو RuboCop لـ Ruby، موجهة إلى عقد API الخاص بك بدلاً من كود التطبيق الخاص بك. إذا كنت قد تمنيت يومًا أن تتم أتمتة مراجعة تصميم API بنفس طريقة تنسيق الكود، فهذا بالضبط ما يفعله المحلل.
ما الذي يراجعه محلل OpenAPI فعليًا
يعمل المحلل على ملف المواصفات، وليس على خادم قيد التشغيل. وجهه إلى openapi.yaml وسيقوم بالمرور على كل مسار، وعملية، ومعامل، ومخطط، واستجابة، وتطبيق القواعد واحدة تلو الأخرى. تندرج القواعد ضمن عدة فئات.
الصلاحية. هل هذه وثيقة OpenAPI قانونية؟ هل يحل كل $ref؟ هل الكلمات الرئيسية المطلوبة موجودة؟ يتداخل هذا مع التحقق البسيط من المخطط، وتقوم معظم المحللات بذلك كخط أساس قبل أي شيء آخر.
الاكتمال. هل تحتوي كل عملية على operationId وملخص ووصف؟ هل يصف كل معامل نفسه؟ هل يحمل كل مخطط example؟ هذه هي القواعد التي تجعل الوثائق وحزم تطوير البرامج (SDKs) التي يتم إنشاؤها قابلة للاستخدام فعليًا، وهي القواعد التي ينساها البشر أكثر من غيرها.
الاتساق. هذا هو الجائزة الحقيقية. تستخدم أسماء الخصائص اصطلاح حالة واحد. أجزاء المسار هي أسماء جمعية. تشترك استجابات الأخطاء في شكل واحد. تعلن كل استجابة 2xx عن application/json. تُستخدم رموز الحالة بالطريقة التي يقصدها مواصفات HTTP. لا شيء من هذه الأخطاء بمعزل عن غيرها؛ مجتمعة هي الفرق بين واجهة برمجة تطبيقات تبدو مصممة وواجهة برمجة تطبيقات تبدو مجمعة.
النمط الداخلي. اتفاقياتك الخاصة. ربما يجب وضع علامات على كل نقطة نهاية. ربما يجب أن تُرجع DELETE الرمز 204. ربما يجب أن تُسبق الحقول الداخلية فقط ببادئة. هذه هي القواعد التي لا يمتلكها أحد آخر، والقدرة على كتابتها هي ما يميز المحلل الذي يمكنك التعايش معه عن المحلل الذي تقاومه.
القاعدة لها مستوى خطورة: خطأ، تحذير، معلومات، أو تلميح. الأخطاء تفشل البناء؛ التحذيرات تظهر ولكن تسمح له بالمرور. هذا المؤشر الزمني للخطورة هو ما يسمح لك بتبني التحليل على واجهة برمجة تطبيقات موجودة دون الغرق في 4000 انتهاك في اليوم الأول. ابدأ كل شيء كتحذير، وأصلح الأسوأ، ثم ارفع القواعد إلى مستوى الخطأ تدريجيًا. بالنسبة للجانب المفاهيمي حول سبب أهمية هذه القواعد وكيف تفرضها الفرق على نطاق واسع، فإن الخلفية الأعمق موجودة في كيف تضمن الشركات الكبرى اتساق تصميم API.
خيارات محلل OpenAPI الرئيسية
فيما يلي الأدوات التي تستحق المعرفة، مع قراءة صادقة حول مكان كل منها.
Spectral
Spectral، من Stoplight، هو المعيار الفعلي. إنه واجهة سطر أوامر (CLI) ومكتبة مفتوحة المصدر تقوم بتحليل OpenAPI 2.0 و 3.x (و AsyncAPI، وأي JSON أو YAML عبر JSONPath). يأتي مع مجموعة قواعد spectral:oas مدمجة تغطي القواعد البديهية، وتكمن قوته الحقيقية في القواعد المخصصة: تصف ما يجب التحقق منه باستخدام محددات given بنمط JSONPath بالإضافة إلى دالة then، وكل ذلك في ملف YAML. توجد كتالوج كبير من الوظائف المدمجة (truthy، pattern، casing، length، enumeration) ويمكنك الانتقال إلى JavaScript عندما تحتاج إلى منطق لا يمكن التعبير عنه في التنسيق التصريحي.

نقاط القوة: إنه في كل مكان، ولديه أكبر نظام بيئي للقواعد، وتوجد ملحقات محرر لـ VS Code وغيرها، ويعمل في أي مكان يعمل فيه Node. إذا كنت تريد أداة واحدة يتعرف عليها الصناعة بأكملها، فهذه هي. المقايضة هي أن كتابة قواعد غير تافهة تعني تعلم JSONPath، وفي النهاية، واجهة برمجة تطبيقات Spectral. لدينا دليل تفصيلي كامل حول ذلك في بناء قواعد Spectral مخصصة باستخدام TypeScript إذا كنت ترغب في التعمق في التأليف.
ملف .spectral.yaml بسيط:
extends: ["spectral:oas"]
rules:
operation-operationId: error
operation-description: warn
property-casing:
description: Properties must be camelCase
given: $.components.schemas..properties[*]~
severity: error
then:
function: casing
functionOptions:
type: camel
قم بتشغيله:
npx @stoplight/spectral-cli lint openapi.yaml
Redocly CLI
Redocly CLI يجمع بين التحليل والتجميع ومعاينة المستندات. يقوم محلله بقراءة ملف تكوين redocly.yaml، ويأتي مع مجموعة من القواعد المدمجة، ويدعم مجموعات قواعد قابلة للتكوين بالإضافة إلى الإضافات المخصصة المكتوبة في JavaScript. تحصل الفرق التي تستخدم Redocly بالفعل للتوثيق على التحليل في نفس سلسلة الأدوات دون إضافة تبعية، وتميل القواعد المدمجة نحو ما يجعل المستندات تُعرض بشكل جيد.

نقاط القوة: تكامل محكم مع سير عمل المستندات والتجميع، إعدادات افتراضية جيدة، وتنسيق تكوين يبدو مألوفًا إذا كنت تعيش في نظام Redocly البيئي. إذا لم تكن هناك بالفعل، فإن مكتبة القواعد أصغر من Spectral، وقصة القواعد المخصصة موثقة بشكل أقل انتشارًا.
npx @redocly/cli lint openapi.yaml
Vacuum
Vacuum هو محلل أحدث مكتوب بلغة Go، مصمم للسرعة. وهو متوافق مع مجموعات قواعد Spectral، لذا يمكنك توجيهه إلى ملف .spectral.yaml موجود والحصول على نفس الفحوصات تعمل بشكل أسرع بكثير على المواصفات الكبيرة. بالنسبة لمستودع مشاريع أحادية (monorepo) يحتوي على عشرات من وثائق API الكبيرة، فإن فرق وقت التشغيل حقيقي.

نقاط القوة: سريع، متوافق مع مجموعات قواعد Spectral، ثنائي واحد بدون وقت تشغيل Node. إذا كانت مواصفاتك صغيرة، فإن مكاسب السرعة غير مرئية، والنظام البيئي وأدوات التحرير أصغر سنًا من Spectral، لذا فهو جذاب أكثر كمسرع لـ CI بدلاً من كونه اختيارًا من الصفر.
Swagger و openapi-spec-validator
تجدر الإشارة إليها حتى لا تخلط بينها وبين المحللات. يقوم محرر Swagger وأدوات swagger-cli/openapi-spec-validator بالتحقق مما إذا كانت الوثيقة صالحة كـ OpenAPI. هذا هو التحقق من الصلاحية فقط، وليس الاتساق أو النمط الداخلي. سيمررون بكل سرور مواصفات حيث يتم تسمية كل خاصية بشكل مختلف، لأنه لا يوجد شيء في مواصفات OpenAPI يمنع ذلك. التحقق ضروري، ولكنه الحد الأدنى، وليس الأقصى. إذا كنت تختار بين أدوات عائلة Swagger ومنصة تصميم كاملة، فإن المقايضات موضحة في بدائل Swagger التي تختبر واجهة برمجة التطبيقات الخاصة بك أيضًا.
فحوصات وقت التصميم في Apidog
تعمل الأدوات المذكورة أعلاه بعد أن يكون لديك ملف. المكان الآخر لاكتشاف عدم الاتساق هو قبل وجود الملف، أثناء تصميم نقطة النهاية. Apidog هي منصة تعتمد على التصميم أولاً: تقوم ببناء نقاط النهاية ومخططات البيانات في محرر مرئي، وتحافظ على اتساق مشروعك داخليًا أثناء العمل. تعني مخططات البيانات القابلة لإعادة الاستخدام أن نفس النموذج يُشار إليه في كل مكان بدلاً من إعادة تعريفه لكل نقطة نهاية، مما يقتل فئة كاملة من انحراف التسمية من المصدر. تفعل مكونات الاستجابة المشتركة نفس الشيء لأشكال الأخطاء.
Apidog ليس بديلاً مباشرًا لمجموعة قواعد Spectral؛ إذا التزمت بقواعد .spectral.yaml، فاستمر في تشغيلها. ما يغيره Apidog هو مقدار ما يجده محللك في المقام الأول. عندما تفرض واجهة التصميم إعادة الاستخدام، ينتقل المحلل من جدار من الانتهاكات إلى اكتشاف عرضي. ولأن Apidog يستورد ويصدر معيار OpenAPI 3.x، فإن الملف الذي تسلمه إلى Spectral أو Vacuum في CI هو نفس العنصر، لذا تتراكم الطبقتان بدلاً من التنافس.
إعداد محلل يمكنك تشغيله اليوم
يعمل الإعداد الجيد على تشغيل الفحص في ثلاثة أماكن، لكل منها مهمة مختلفة. يوفر المحرر ملاحظات فورية. يوقف الخطاف المسبق للالتزام (pre-commit hook) الأخطاء الواضحة محليًا. CI هو البوابة التي لا يمكن لأحد تجاوزها. إليك كل طبقة.
الطبقة 1: المحرر
قم بتثبيت إضافة Spectral VS Code وأضف ملف .spectral.yaml إلى جذر مستودعك. تلتقطه الإضافة تلقائيًا وتضع خطوطًا تحت الانتهاكات أثناء تحرير المواصفات، بنفس الطريقة التي يحصل بها الخطأ المطبعي على خط أحمر متعرج. هذه هي أرخص حلقة تغذية راجعة ممكنة، لأن المطور يحل المشكلة قبل أن تصبح التزامًا. لا شيء آخر لتكوينه؛ الملف في المستودع هو المصدر الوحيد للحقيقة بشأن القواعد.
الطبقة 2: ما قبل الالتزام (pre-commit)
أضف خطافًا (hook) حتى لا يصل المواصفات المعيبة أبدًا إلى المستودع البعيد. يكفي استخدام نص برمجي في package.json بالإضافة إلى خطاف Git:
{
"scripts": {
"lint:api": "spectral lint openapi.yaml --fail-severity=error"
}
}
# .git/hooks/pre-commit (أو عبر husky)
#!/bin/sh
npm run lint:api || {
echo "فشل تحليل OpenAPI. أصلح المواصفات قبل الالتزام."
exit 1
}
علامة --fail-severity=error هي الجزء المهم. تخبر المحلل بالخروج برمز غير صفري فقط عند وجود أخطاء، لذا لا تزال التحذيرات تطبع دون حظر الالتزام. هذا يحافظ على قابلية استخدام الخطاف بينما لا تزال ترفع مستوى القواعد.
الطبقة 3: التكامل المستمر (CI)
هذه هي البوابة المهمة، لأنها تلك التي لا يستطيع زميل في الفريق تجاوزها باستخدام --no-verify. خطوة GitHub Actions:
name: API lint
on: [pull_request]
jobs:
spectral:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npx @stoplight/spectral-cli lint openapi.yaml --fail-severity=error
تفشل المهمة عندما تكسر المواصفات قاعدة بمستوى خطأ، ويظهر طلب السحب علامة حمراء، ويتم حظر الدمج حتى يقوم أحدهم بإصلاحها. هذه هي آلية التنفيذ بأكملها. لا توجد لوحات معلومات، ولا إزعاج؛ القاعدة إما خضراء أو ليست كذلك.
الطبقة 4: اختبار واجهة برمجة التطبيقات التي تصفها المواصفات
يثبت المحلل أن المواصفات جيدة التكوين ومتسقة. لكنه لا يقول شيئًا عما إذا كانت واجهة برمجة التطبيقات قيد التشغيل تتطابق مع المواصفات. هذه الفجوة هي حيث يختبئ انحراف العقد: وثيقة تم تحليلها بشكل جميل تصف سلوكًا توقف الخادم عن احترامه قبل ثلاثة إصدارات. لإغلاقها، تقوم بإجراء اختبارات على واجهة برمجة التطبيقات الحية في نفس مسار العمل.
هذا هو المكان الذي تتناسب فيه واجهة سطر أوامر Apidog بجانب محللك. إنها حزمة npm، apidog-cli، وتقوم بتشغيل سيناريوهات اختبار Apidog الخاصة بك من سطر الأوامر حتى تتناسب مع CI مباشرة بعد خطوة التحليل:
npm install -g apidog-cli
apidog run --access-token $APIDOG_ACCESS_TOKEN -t 605067 -e 1629989 -r cli,junit
يخرج أمر apidog run بقيمة غير صفرية عندما يفشل الاختبار، وهو نفس العقد الذي تعتمد عليه كل خطوة من خطوات CI، لذلك يؤدي الاختبار الفاشل إلى حظر الدمج تمامًا كما يفعل التحليل الفاشل. يُصدر تقرير -r junit ملف XML تقوم لوحة تحكم CI بتحليله إلى شجرة نجاح/فشل، ويشير -e إلى نفس السيناريوهات في بيئة الاختبار أو الإنتاج دون تكرارها. يمكن لـ CLI أيضًا import وثيقة OpenAPI 3.x، لذلك فإن الملف الذي يفحصه محللك هو نفس الملف الذي تختبره Apidog. للحصول على نمط مسار العمل الكامل، بما في ذلك التقارير ومعالجة رمز الخروج، راجع الدليل على تشغيل Apidog CLI في مسار CI/CD الخاص بك. إذا كنت تستخدم GitHub على وجه التحديد، فإن Apidog CLI في GitHub Actions لديه سير عمل جاهز للنسخ واللصق.
قم بالتحليل أولاً، ثم الاختبار ثانيًا. خطوة التحليل سريعة وتلتقط مشاكل التصميم؛ خطوة الاختبار أبطأ وتلتقط مشاكل السلوك. قم بتشغيلها كمرحلتين ويجب أن يجتازهما طلب السحب.
اختيار واعتماد مجموعة قواعد دون عناء
اختيار الأداة هو الجزء السهل. تبنيها على واجهة برمجة تطبيقات موجودة بالفعل هو ما تتوقف عنده الفرق، لأن التشغيل الأول على مواصفات ناضجة يعيد مئات الانتهاكات، ورد الفعل الواضح هو إيقاف كل شيء.
لا تبدأ من قواعد صفرية ولا تبدأ من كل قاعدة على أنها خطأ. ابدأ من مجموعة القواعد المدمجة (spectral:oas) مع تعيين كل ما تضيفه إلى warn. قم بتشغيله، واقرأ العدد، وأصلح أخطاء الصلاحية أولاً لأنها أخطاء حقيقية. ثم اختر قاعدتين أو ثلاث قواعد اتساق تهم عملاءك أكثر (عادةً ما تكون حالة الخاصية وشكل خطأ واحد) وقم بترقيتها إلى error فقط. كل شيء آخر يبقى تحذيرًا. في كل سبرنت، قم بترقية تحذير أو اثنين آخرين إلى أخطاء مع تحديث قاعدة الكود. في غضون ربع سنة، يتم فرض مجموعة القواعد بأكملها ولم يضطر أحد إلى التوقف عن الشحن للوصول إلى هناك.
اكتب قواعد النمط الداخلي باعتدال. كل قاعدة مخصصة هي كود يجب على شخص ما صيانته وشرحه للموظف التالي. تكسب القاعدة مكانها فقط عندما يكون الانتهاك قد أضر بك بالفعل، وليس لمجرد أنه قد يحدث. بالنسبة للقواعد التي تكتبها، اعتمد على طبقة التصميم لجعلها نادرة: إذا تم إعادة استخدام مخططاتك من تعريف مركزي، فإن قاعدة حالة الخاصية نادرًا ما تعمل لأن هناك مكانًا واحدًا يتم فيه تعريف الاسم. الإطار المفاهيمي للقواعد التي تستحق التنفيذ، مقابل القواعد التي هي مجرد تفاصيل تافهة، مغطى في أفضل ممارسات تصميم API.
إذا كنت تصمم بلغة مختلفة عن YAML الخام، فإن المحلل لا يزال ينطبق. يقوم TypeSpec بالتحويل إلى OpenAPI، وتقوم بتحليل الوثيقة الصادرة بنفس الطريقة؛ لا يهتم المحلل بكيفية تأليف الملف، بل بما يقوله.
مكان المحلل في حلقة التصميم الأكبر
المحلل هو عنصر تحكم واحد في سير عمل يعتمد على التصميم أولاً، وليس كل شيء. الحلقة الكاملة هي: تصميم العقد، تحليله، محاكاته حتى يتمكن العملاء من البناء عليه، اختبار التنفيذ مقابله، ونشر المستندات منه. تخطى أي خطوة وتفقد الخطوات الأخرى قيمتها. مواصفات تم تحليلها ولكن لم يتم محاكاتها لا تزال تعيق العمل الأمامي. مواصفات تم محاكاتها ولكن لم يتم اختبارها لا تزال تنحرف عن الواقع.
السبب في وضع التصميم أولاً في تلك الحلقة هو نفس السبب الذي يجعل التحليل يعمل: اكتشاف المشاكل حيث تكون تكلفة إصلاحها أقل. تغيير اسم خاصية في أداة التصميم هو تعديل واحد. تغييرها بعد أن تكون ثلاثة فرق قد شحنت بناءً على الاسم القديم هو ترحيل. يفرض المحلل الاتساق على الملف؛ تفرض عملية التصميم أولاً الاتساق على القرار قبل وجود الملف. إذا كنت تريد الحجة الأوسع للتسلسل، فإن API-first مقابل API design-first مقابل code-first يوضح المقايضات، وأدوات تصميم API المبنية على العقد أولاً تغطي الأدوات التي تدعم ذلك.
Apidog يغطي تلك الحلقة بأكملها في مكان واحد: التصميم بمخططات قابلة لإعادة الاستخدام، المحاكاة الفورية، الاختبار باستخدام واجهة سطر الأوامر (CLI) في CI، وتصدير OpenAPI نظيف لأي محلل تختاره كمعيار. لا يزال للمحلل وظيفته؛ لكن ما يكتشفه يكون أقل.
