حل تعارض أسماء الروابط بإضافة لاحقة رقمية متسلسلة
تقارن أداة حل التعارض اسم الرابط المطلوب كما هو بأسماء الروابط المستخدمة مسبقا. إذا كان متاحا، تعيده دون تغيير. وإذا كان محجوزا، تختبر بدائل رقمية مثل -2 و-3 وما بعدها حتى تعثر على أول قيمة متاحة. وهي لبنة صغيرة وحتمية لأنظمة النشر وعمليات الاستيراد ومولدات الوثائق وأي سير عمل يحتاج إلى تعيين مسار URL فريد من دون استبدال محتوى موجود عن غير قصد.
شغّل الأداة مجانًا
حافظوا على اسم الرابط المطلوب كلما أمكن
ينبغي لأداة حل التعارض الجيدة ألا تغير عنوان URL إلا عند الضرورة. أرسلوا القيمة المقترحة في desired_slug، وضعوا كل القيم المحجوزة في used_slugs. تجري المقارنة بصورة تامة مع مراعاة حالة الأحرف. إذا لم تظهر القيمة المقترحة ضمن المجموعة المستخدمة، تتضمن النتيجة اسم الرابط الأصلي وتبين عدم وقوع تعارض. لا تحول الأداة الأحرف، ولا تزيل المسافات الطرفية، ولا تنقل الكتابة، ولا تستبدل علامات الترقيم، لأن هذه التحويلات تخص خطوة إنشاء اسم الرابط قبل فحص التفرد. إن فصل المسؤوليتين يمنع تغييرات URL غير المتوقعة ويجعل النتائج قابلة لإعادة الإنتاج في عمليات البناء والترحيل والاختبار. وترفض الأداة اسم الرابط المطلوب إذا كان فارغا بدلا من تحويله إلى لاحقة اعتباطية، لأن ذلك قد يخفي عنوانا مفقودا أو ربطا معيبا في مرحلة سابقة. ولا تؤثر القيم المكررة في قائمة الأسماء المستخدمة في الإجابة، إذ تدمجها عملية البحث تلقائيا، فلا يلزم تنظيف القائمة للحصول على نتيجة ثابتة.
اختاروا أول لاحقة رقمية متاحة
عندما يكون اسم الرابط المطابق محجوزا، يبدأ اختيار اللاحقة من 2، وفقا للعرف الشائع الذي يجعل المسار بلا لاحقة للعنصر الأول ويمنح العنصر التالي -2. ثم تفحص الأداة القيم المرشحة تصاعديا: desired-2 ثم desired-3 ثم desired-4 وهكذا. وتتوقف عند أول قيمة غير موجودة في المجموعة المقدمة، ولذلك تعاد الاستفادة من الفجوات بصورة متوقعة. فمثلا، إذا كانت report وreport-2 وreport-4 محجوزة، تكون النتيجة report-3. تشمل المقارنة السلسلة كاملة، لذلك لا تسبب قيم غير مرتبطة مثل annual-report أو report-old تعارضا. وتعامل النهاية الرقمية الموجودة أصلا بوصفها جزءا حرفيا من القيمة المطلوبة، فلا تحللها ولا تعيد كتابتها؛ فإذا طلبتم release-2 وكان محجوزا، يصبح أول مرشح release-2-2. يمنع هذا السلوك الواضح تخمين مقصد المستخدم، ويضمن أن المدخلات المتطابقة تعطي دائما المخرجات نفسها من دون الاعتماد على قاعدة بيانات أو ساعة أو عشوائية أو إعداد لغوي أو ترتيب التنفيذ.
استخدموا النتيجة بأمان في مسارات النشر
تفيد هذه القدرة عندما يكون تطبيقكم على علم مسبق بأسماء الروابط المحجوزة. اجمعوا تلك القيم وأرسلوها مع الاسم المطلوب، ثم استخدموا القيمة المعادة للسجل الجديد. تبين الاستجابة أيضا هل وقع تعارض، وتذكر الرقم المختار عندما تكون النتيجة ذات لاحقة. ويمكن الاستفادة من هذه البيانات في السجلات والمعاينات أو في رسالة تشرح سبب اختلاف URL عن الاقتراح الأصلي. لا تحجز العملية القيمة المعادة، ولذلك ينبغي للأنظمة التي تسمح بكتابات متزامنة أن تفرض قيد التفرد وأن تعيد المحاولة بقائمة محدثة إذا حجزت عملية أخرى الاسم نفسه. وفي الاستيراد الدفعي، أضيفوا كل تعيين ناجح إلى المجموعة المحلية قبل معالجة الصف التالي. ولأن المقارنة تامة، طبقوا سياسة URL الخاصة بكم بصورة متسقة قبل هذه الخطوة، واستخدموا مولد أسماء روابط إذا احتجتم إلى توحيد حالة الأحرف أو Unicode أو المسافات أو علامات الترقيم. تبلغ كلفة كل طلب API مقدار $0.002، ويمكن تشغيل المنطق الحتمي نفسه في المتصفح لإجراء فحوص تفاعلية.
حالات الاستخدام
انشروا صفحة من دون استبدال صفحة أخرى
احتفظوا بالمسار الذي يفضله المحرر إذا كان متاحا، أو عينوا أول بديل رقمي متاح إذا كان محجوزا.
استوردوا سجلات بعناوين URL فريدة وثابتة
قارنوا كل اسم رابط مجهز بالمسارات الموجودة والمعينة حديثا لكي تحصل العناوين المكررة على لواحق حتمية.
أنشئوا مسارات للوثائق
امنعوا العناوين أو الصفحات المولدة المكررة من حجز المسار نفسه، مع الحفاظ على مسارات مقروءة ومتوقعة.
الأسئلة الشائعة
ماذا يحدث إذا كان اسم الرابط المطلوب متاحا؟
يعاد دون تغيير، وتكون collision بقيمة false.
ما اللاحقة التي تختبر أولا؟
تبدأ الأداة من -2، ثم تختبر -3 و-4 والقيم الأعلى حتى تعثر على أول قيمة متاحة.
هل تحول الأداة النص إلى اسم رابط مناسب لعنوان URL؟
لا. إنها تقارن القيمة المستلمة كما هي وتضيف إليها. استخدموا مولد أسماء الروابط أولا إذا احتجتم إلى توحيد الأحرف أو المسافات أو الترقيم أو Unicode.
هل تراعي المقارنة حالة الأحرف؟
نعم. Product وProduct متطابقتان، أما Product وproduct فتعاملان كسلسلتين مختلفتين.
هل تحجز القدرة اسم الرابط المعاد؟
لا. إنها تحسب قيمة مرشحة من القائمة المقدمة. يجب على طبقة التخزين فرض التفرد عند كتابة السجل.
ما كلفة طلب API؟
تبلغ كلفة كل طلب $0.002.
للمطوّرين — الوصول عبر API
كل ما في هذه الصفحة متاح برمجيًا. هذا القسم موجّه للفرق التقنية التي تريد ربط الأداة بأنظمتها الخاصة؛ بقية المستخدمين يمكنهم استخدام الأداة أعلاه مباشرة دون الحاجة لقراءة ما يلي.
الـEndpoint
صادِق على طلبك بترويسة Bearer، وأرسل طلب POST واحدًا لتدخل مهمتك قائمة التنفيذ فورًا؛ ثم تستلم النتيجة عبر webhook أو رابط موقّع.
استدعِ الخدمة من بيئتك
curl -X POST https://api.kit.forhosting.com/dev/slug-collision-resolve \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"desired_slug":"product-guide","used_slugs":["product-guide","product-guide-2"]}'const res = await fetch("https://api.kit.forhosting.com/dev/slug-collision-resolve", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"desired_slug": "product-guide",
"used_slugs": [
"product-guide",
"product-guide-2"
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/dev/slug-collision-resolve",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"desired_slug": "product-guide",
"used_slugs": [
"product-guide",
"product-guide-2"
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/dev/slug-collision-resolve", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"desired_slug":"product-guide","used_slugs":["product-guide","product-guide-2"]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"desired_slug":"product-guide","used_slugs":["product-guide","product-guide-2"]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/dev/slug-collision-resolve", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)مثال على الطلب
{
"desired_slug": "product-guide",
"used_slugs": [
"product-guide",
"product-guide-2"
]
}مثال على الاستجابة
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "dev.slug_collision_resolve",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}الواجهة غير متزامنة: تستلم task_id فور الإرسال، ويمكنك الاستعلام عن الحالة بمعدل طلب واحد في الثانية.
الأسعار
السعر معلن كما تراه: لا tokens ولا نظام نقاط؛ وإن فشلت المهمة فلن تُحاسَب عليها.
الحدود
max_used_slugs | 10000 |
max_slug_chars | 10000 |
الأخطاء
| HTTP | الرمز | المعنى |
|---|---|---|
401 | unauthorized | مفتاح الوصول مفقود أو غير صالح؛ تحقق من ترويسة Bearer في طلبك. |
402 | insufficient_balance | رصيدك لا يكفي لتنفيذ هذه المهمة؛ أعد شحن الرصيد ثم أعد المحاولة. |
404 | unknown_type | نوع المهمة المطلوب غير موجود في الكتالوج — راجع الاسم المرسل في الطلب. |
429 | rate_limited | تجاوزت الحد المسموح من الطلبات؛ انتظر قليلًا ثم أعد المحاولة. |