* feat(docs): mirror every docs/ page in all 65 locales Extends the documentation mirrors from the 22-page core set (#13940) to every Markdown page under docs/: 152 sources x 65 locales = 9,880 mirrors (6,208 new), language bars rewritten for the full locale list, state adopted so the blocking drift gate now covers all 152 pages. run-translation.mjs: an oversized block made only of table rows or list items (PROVIDER_REFERENCE.md 244-row table, FREE_TIERS.md 71-item list) is cut at item boundaries and rejoined without a blank line — the single 16-40 KB request outlived the backend socket for verbose scripts. 48 older mirrors whose tables had lost rows were retranslated with --force. * docs(i18n): refresh mirrors for the sources the base changed since the branch cut Section-level retranslation of the 29 docs (and README.md) whose source or mirrors moved on release/v3.8.51 during the run, then state adoption; the drift gate is green again on the merged tree.
16 KiB
Webhooks (العربية)
🌐 Languages: 🇺🇸 English · 🇪🇹 am · 🇦🇿 az · 🇧🇬 bg · 🇧🇩 bn · 🇨🇿 cs · 🇩🇰 da · 🇩🇪 de · 🇬🇷 el · 🇪🇸 es · 🇪🇪 et · 🇮🇷 fa · 🇫🇮 fi · 🇫🇷 fr · 🇮🇪 ga · 🇮🇳 gu · 🇳🇬 ha · 🇮🇱 he · 🇮🇳 hi · 🇭🇷 hr · 🇭🇺 hu · 🇦🇲 hy · 🇮🇩 id · 🇳🇬 ig · 🇮🇹 it · 🇯🇵 ja · 🇬🇪 ka · 🇰🇭 km · 🇮🇳 kn · 🇰🇷 ko · 🇱🇹 lt · 🇱🇻 lv · 🇮🇳 ml · 🇮🇳 mr · 🇲🇾 ms · 🇲🇹 mt · 🇲🇲 my · 🇳🇵 ne · 🇳🇱 nl · 🇳🇴 no · 🇮🇳 or · 🇮🇳 pa · 🇵🇭 phi · 🇵🇱 pl · 🇵🇹 pt · 🇧🇷 pt-BR · 🇷🇴 ro · 🇷🇺 ru · 🇱🇰 si · 🇸🇰 sk · 🇸🇮 sl · 🇷🇸 sr · 🇸🇪 sv · 🇰🇪 sw · 🇮🇳 ta · 🇮🇳 te · 🇹🇭 th · 🇹🇷 tr · 🇺🇦 uk-UA · 🇵🇰 ur · 🇺🇿 uz · 🇻🇳 vi · 🇳🇬 yo · 🇨🇳 zh-CN · 🇹🇼 zh-TW
المصدر الموثوق:
src/lib/webhookDispatcher.ts،src/lib/db/webhooks.ts،src/app/api/webhooks/آخر تحديث: 2026-06-28 — v3.8.40
يمكن لـ OmniRoute إرسال خطافات ويب HTTP عند وقوع أحداث على المنصة. استخدمها للتكامل مع Slack أو PagerDuty أو Datadog أو خدمات التنبيه الداخلية أو أي مستقبِل HTTP.
يوقّع المرسِل كل عملية تسليم باستخدام HMAC-SHA256، ويعيد المحاولة عند حدوث أعطال مؤقتة، ويتتبع سلامة التسليم لكل خطاف ويب، ويعطّل تلقائيًا نقاط النهاية التي يستمر فشلها.
الأحداث المدعومة
يمثّل النوع WebhookEvent (src/lib/webhooks/eventDescriptions.ts، ويستخدمه src/lib/webhookDispatcher.ts) حاليًا أربعة أحداث بالضبط:
| الحدث | وقت الإطلاق |
|---|---|
request.completed |
عند اكتمال طلب وكيل بنجاح |
request.failed |
عند فشل طلب وكيل بعد استنفاد جميع محاولات الإعادة/البدائل |
quota.exceeded |
عند تجاوز مفتاح API حدًا للميزانية/الحصة |
test.ping |
حدث اصطناعي تستخدمه نقطة نهاية الاختبار |
تقبل الاشتراكات القيمة الحرفية "*" لتلقّي كل حدث. تُتجاهل أسماء الأحداث
غير المعروفة في events أثناء الإرسال.
ملاحظة: واجهة API الخاصة بالمرسِل موصولة، لكن مواضع الاستدعاء الإنتاجية لبعض الأحداث غير التابعة لـ
test.pingلا تزال قيد الإضافة. تحقّق منgrep dispatchEventلمعرفة المسارات التي تستدعي المرسِل حاليًا في إصدارك.
البنية
المستدعي (معالج، خدمة، مراقب)
dispatchEvent(event, data) [src/lib/webhookDispatcher.ts]
-> getEnabledWebhooks() [src/lib/db/webhooks.ts]
-> التصفية حسب webhook.events
-> لكل تطابق (بالتوازي):
deliverWebhook(url, payload, secret)
إنشاء الحمولة { event, timestamp, data }
توقيع النص باستخدام HMAC-SHA256 (إذا كان السر موجودًا)
POST بمهلة 10 ثوانٍ
إعادة المحاولة حتى 3 مرات عند أخطاء 5xx / أخطاء الشبكة
recordWebhookDelivery(id, status, success)
-> disableWebhooksWithHighFailures(10)
يتم الإرسال بنمط الإطلاق دون انتظار بالنسبة إلى المستدعي: تتجاهل Promise.allSettled
الأخطاء الخاصة بكل خطاف ويب، بحيث لا يمكن لمستقبِل معطّل واحد حظر المستقبِلات الأخرى.
توقيع HMAC
عندما يكون لخطاف الويب secret، يوقّع OmniRoute نص JSON ويرسل:
Content-Type: application/json
User-Agent: OmniRoute-Webhook/1.0
X-Webhook-Event: <event>
X-Webhook-Timestamp: <ISO-8601>
X-Webhook-Signature: sha256=<hex HMAC-SHA256(secret, body)>
تستخدم أسماء الترويسات البادئة
X-Webhook-*(وليسX-OmniRoute-*). قيمة التوقيع هيsha256=<hex>— تحقّق من البادئة كاملةً.
إذا استُدعيت createWebhook دون سر، فستُنشئ وحدة DB سرًا
(whsec_<48 hex>) بحيث تكون جميع خطافات الويب موقّعة افتراضيًا.
التحقّق لدى المستقبِل
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(rawBody: string, signature: string, secret: string) {
const expected = "sha256=" + createHmac("sha256", secret).update(rawBody).digest("hex");
const a = Buffer.from(expected);
const b = Buffer.from(signature);
return a.length === b.length && timingSafeEqual(a, b);
}
تحقّق دائمًا باستخدام نص الطلب الخام قبل أي تحليل لـ JSON.
سياسة إعادة المحاولة والفشل
deliverWebhook(url, payload, secret, maxRetries = 3):
- مهلة قدرها 10 ثوانٍ لكل محاولة (
AbortController). - تُعدّ استجابات HTTP 2xx نجاحًا.
- تُعدّ استجابات HTTP 3xx/4xx حالة نهائية غير قابلة لإعادة المحاولة — ويُسجَّل التسليم
مع
success = res.ok. - يُعاد إجراء المحاولة عند استجابات HTTP 5xx وأخطاء الشبكة، باستخدام تراجع أُسّي:
2^attempt * 1000 ms(1s، 2s، 4s). - بعد
maxRetries، يُسجَّل التسليم على أنه فاشل. - يحدّث كل تسليم
last_triggered_atوlast_status، ويعيد تعيينfailure_countأو يزيده. - يستدعي الموزّع
disableWebhooksWithHighFailures(10)بعد كل عملية توزيع، لذلك يُعطَّل تلقائيًا أي webhook تكون فيهfailure_count >= 10.
قاعدة البيانات
الجدول webhooks (الترحيل 011_webhooks.sql):
| العمود | النوع | ملاحظات |
|---|---|---|
id |
TEXT PK | UUID |
url |
TEXT | عنوان URL للوجهة |
events |
TEXT | مصفوفة JSON؛ القيمة الافتراضية ["*"] |
secret |
TEXT | سر HMAC (يُنشأ تلقائيًا إذا لم يُحدَّد) |
enabled |
INT | 0/1؛ القيمة الافتراضية 1 |
description |
TEXT | تسمية وصفية اختيارية |
created_at |
TEXT | datetime('now') |
last_triggered_at |
TEXT | يُحدَّث عند كل محاولة تسليم |
last_status |
INT | حالة HTTP للمحاولة الأخيرة (0 = الشبكة) |
failure_count |
INT | يُعاد تعيينه إلى 0 عند النجاح، ويُزاد 1 عند الفشل |
يُحفَظ سجل التسليم في الجدول المخصص webhook_deliveries
(الترحيل 069_webhook_deliveries.sql، وتتم الكتابة عبر
src/lib/db/webhookDeliveries.ts::insertDelivery عند كل محاولة)، بالإضافة
إلى العدادات المجمّعة في صف webhooks. أُضيفت بيانات النوع الوصفية (Slack / Discord /
Telegram / محوّلات الحمولات المخصصة) بواسطة 070_webhooks_kind_metadata.sql.
واجهة REST API
تتطلب جميع نقاط النهاية مصادقة الإدارة (requireManagementAuth).
| نقطة النهاية | الطريقة | الوصف |
|---|---|---|
/api/webhooks |
GET | سرد webhooks (مع إخفاء الأسرار) |
/api/webhooks |
POST | إنشاء webhook |
/api/webhooks/[id] |
GET | تفاصيل webhook (السر الكامل) |
/api/webhooks/[id] |
PUT | تحديث الحقول |
/api/webhooks/[id] |
DELETE | إزالة |
/api/webhooks/[id]/test |
POST | إرسال test.ping (من دون إعادة محاولات) |
/api/webhooks/[id]/deliveries |
GET | محاولات التسليم الأخيرة لـ webhook واحد |
/api/webhooks/validate-url |
POST | التحقق المسبق من عنوان URL (حماية SSRF) |
يخفي GET /api/webhooks السر بصيغة <أول 10 أحرف>... لتجنّب تسريبه
في صفحات القوائم. استخدم طلب GET الخاص بـ [id] عندما تحتاج فعليًا إلى السر.
إنشاء webhook
curl -X POST http://localhost:20128/api/webhooks \
-H "Cookie: auth_token=..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://hooks.slack.com/services/...",
"secret": "whsec_my_shared_secret",
"events": ["quota.exceeded", "request.failed"],
"description": "تنبيهات Slack"
}'
إذا حُذف secret، ينشئ الخادم سرًا بصيغة whsec_<hex> ويعيده
في الاستجابة.
اختبار webhook
curl -X POST http://localhost:20128/api/webhooks/<id>/test \
-H "Cookie: auth_token=..."
يعيد { delivered, status, error }. لا تُجرى أي إعادة محاولة — وهذا مفيد
للتحقق سريعًا من أن المستقبِل يقبل الحمولة والتوقيع.
لوحة التحكم
توفر صفحة لوحة التحكم في /dashboard/webhooks (راجع
src/app/(dashboard)/dashboard/webhooks/page.tsx) ما يلي:
- إنشاء/تعديل خطافات الويب باستخدام منتقي الأحداث
- مؤشر الحالة (نشط / غير نشط / به خطأ) استنادًا إلى
enabledوfailure_countوlast_status - إرسال اختباري بنقرة واحدة
- مفتاح تبديل يدوي للتمكين/التعطيل
أمثلة على الحمولة
request.completed
{
"event": "request.completed",
"timestamp": "2026-05-13T20:30:00.123Z",
"data": {
"trace_id": "...",
"api_key_id": "...",
"provider": "openai",
"model": "gpt-5",
"status": 200,
"tokens_in": 142,
"tokens_out": 350,
"cost_usd": 0.0042
}
}
test.ping
{
"event": "test.ping",
"timestamp": "2026-05-13T20:32:00.000Z",
"data": {
"message": "اختبار تسليم خطاف الويب من OmniRoute",
"webhookId": "<uuid>"
}
}
تُحدَّد أشكال الحقول لأحداث غير test.ping من خلال مواضع الاستدعاء التي تُصدرها؛
تعامل مع الكائن data على أنه متوافق مع الإصدارات المستقبلية (أضف حقولًا، ولا تعتمد على
غيابها).
أفضل الممارسات
- تحقق من التوقيع عند كل عملية تسليم بمقارنته مع النص الخام للطلب — فهذا يمنع طلبات POST المزيفة من أي شخص يخمّن عنوان URL لخطاف الويب الخاص بك.
- استجب برمز 2xx خلال نحو 5 ثوانٍ — تنتهي مهلة الموزّع بعد 10 ثوانٍ. ستستهلك
الجهات المستقبلة البطيئة محاولات إعادة الإرسال وتزيد قيمة
failure_count. - اجعل المعالجات متكافئة النتائج — تعني محاولات إعادة الإرسال ودلالات التسليم مرة واحدة على الأقل احتمال وجود نسخ مكررة.
- اشترك في الحد الأدنى — أدرج فقط الأحداث التي تستهلكها فعليًا؛ ستضيف
"*"تكلفة على الجهات المستقبلة التي لا تتحكم فيها. - راقب
failure_count— تُعطَّل نقاط النهاية تلقائيًا بعد 10 حالات فشل متتالية؛ أعد ضبطها باستدعاءPUT /api/webhooks/[id]معenabled: trueبعد إصلاح الجهة المستقبلة. - بدّل الأسرار دوريًا — أرسل سرًا جديدًا في
secretباستخدامPUT، وانشر القيمة الجديدة إلى الجهة المستقبلة، وأكّدها عبر نقطة نهاية الاختبار.
راجع أيضًا
- API_REFERENCE.md — واجهة API الكاملة للإدارة
- RESILIENCE_GUIDE.md — دلالات قاطع الدائرة / فترة التهدئة
وراء حالات فشل المزوّد الظاهرة عبر
request.failed - المصدر:
src/lib/webhookDispatcher.ts، وsrc/lib/db/webhooks.ts