قوانین مسیریابی چه کمکی میکند؟
Routing Rules به شما اجازه میدهد بر اساس مشخصات درخواست (مثل کشور، مسیر، هدر، IP و …) تنظیمات CDN را در لحظهی دریافت همان درخواست تغییر بدهید؛ مهمترین کاربرد رایج آن انتخاب upstream متفاوت برای بخشی از ترافیک است (مثلاً هدایت کاربران غیرایرانی به یک upstream خارجی).
- ترتیب اجرا مهم است؛ درخواستها با هر قانون به ترتیب تعریفشده بررسی میشوند.
- در حال حاضر تنها action مجاز
setUpstreamمیباشد.
ساختار کلی RoutingRules
RoutingRules یک آرایه از Ruleهاست. هر Rule این فیلدها را دارد:
name: نام قانون (حداکثر 64 کاراکتر)enabled: فعال/غیرفعال بودن قانونconstraints: شرطها (حداکثر 10 گروه OR، و داخل هر گروه حداکثر 10 شرط AND)actions: عملها (حداقل 1 و حداکثر 10)
منطق constraints (Disjunctive Normal Form - DNF)
ساختار constraints از Disjunctive Normal Form (DNF) استفاده میکند؛ یعنی یک آرایهی دوبعدی که به شکل OR از چند گروه AND تفسیر میشود.
تعریف DNF
- لایه بیرونی (Disjunction / OR): گروهها
- لایه داخلی (Conjunction / AND): شرطها داخل هر گروه
فرمول کلی DNF:
(A₁ AND A₂ AND ...) OR (B₁ AND B₂ AND ...) OR (C₁ AND C₂ AND ...)
مثالها
-
constraints: [ [A, B], [C] ]معادل:
(A AND B) OR (C) -
constraints: [ [A, B], [C, D], [E] ]معادل:
(A AND B) OR (C AND D) OR (E) -
constraints: [ [A] ]معادل:
A
نکته مهم: اگر حداقل یکی از گروههای AND برقرار باشد، Rule اجرا میشود.
negate (NOT)
هر شرط میتواند negate: true داشته باشد تا نتیجهی آن شرط معکوس شود (عملگر NOT).
انواع شرطها (Constraint Types) و operatorهای مجاز
هر constraint یک type دارد و دقیقاً یکی از آبجکتهای مربوط به همان type را پر میکند.
country
- operator:
equals - expected: لیست کد کشور (مثلاً
['IR','US'])
path (فقط مسیر بدون query)
- operator:
equals|contains|starts_with|ends_with|matches - expected: لیست مسیرها
uri (مسیر + query)
- operator:
equals|contains|starts_with|ends_with|matches - expected: لیست URIها
host
- operator:
equals|contains|starts_with|ends_with|matches - expected: لیست hostها
header
- operator:
equals|contains|starts_with|ends_with|matches|exists - name: نام هدر
- expected: (اختیاری) لیست مقدارها
cookie
- operator:
equals|contains|starts_with|ends_with|matches|exists - name: نام کوکی
- expected: (اختیاری)
args (Query String)
- operator:
equals|contains|starts_with|ends_with|matches|exists - name: نام پارامتر
- expected: (اختیاری)
ip
- operator:
ip_matches - expected: (اختیاری) لیست CIDRها
- ipSet: (اختیاری) نام IPSet
method
- operator:
equals - expected: متدهای HTTP (
GET,POST,PUT, …)
port
- operator:
equals - expected:
['80']یا['443']
http_version
- operator:
equals - expected: مثل
['HTTP/2'],['HTTP/3']
tls
- operator:
equals - expected:
true/false
known_bots
- operator:
equals - expected:
true/false
asn
- operator:
equals|lesser|greater - expected: لیست عددی ASN
edge
- operator:
equals|contains|starts_with|ends_with|matches - expected: لیست نام edge
actionها در Routing Rules
در حال حاضر تنها action مجاز:
setUpstream
setUpstream.upstreamName: نام upstream مقصد (حداکثر 64 کاراکتر)- upstream باید در همین CDN تعریف شده باشد
مثال عملی
هدف: اگر کاربر ایران نبود و مسیر درخواست با /blog یا /news شروع نمیشد، upstream را روی default-foreign بگذار.
routingRules:
- name: ir
enabled: true
actions:
- type: setUpstream
setUpstream:
upstreamName: default-foreign
constraints:
- - type: country
negate: true
country:
operator: equals
expected: [IR]
- type: path
negate: true
path:
operator: starts_with
expected: [/blog, /news]تفسیر منطقی (DNF):
(country ≠ IR) AND (path NOT starts_with (/blog OR /news))
چون فقط یک گروه AND وجود دارد، در صورت برقرار بودن آن، Rule اجرا میشود.
API و نمونه curl برای Patch کردن RoutingRules
مسیر API
https://api.sotoon.ir/delivery/v2.1/global/workspaces/{workspaceUUID}/cdns/{resourceId}
دریافت CDN (مشاهده مقدار فعلی RoutingRules)
curl -sS \
-H "Authorization: Bearer $TOKEN" \
"https://api.sotoon.ir/delivery/v2.1/global/workspaces/$WORKSPACE_UUID/cdns/$RESOURCE_ID"PATCH با Merge Patch — جایگزینی کامل آرایه spec.routingRules
curl -sS -X PATCH \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/merge-patch+json" \
"https://api.sotoon.ir/delivery/v2.1/global/workspaces/$WORKSPACE_UUID/cdns/$RESOURCE_ID" \
-d '{
"spec": {
"routingRules": [
{
"name": "ir",
"enabled": true,
"actions": [
{
"type": "setUpstream",
"setUpstream": { "upstreamName": "default-foreign" }
}
],
"constraints": [
[
{
"type": "country",
"negate": true,
"country": { "operator": "equals", "expected": ["IR"] }
},
{
"type": "path",
"negate": true,
"path": { "operator": "starts_with", "expected": ["/blog", "/news"] }
}
]
]
}
]
}
}'