Routing Rules
Routing rules (Response Rules, SRR) are an ordered set of rules the panel uses to decide what to return for a subscription request. The decision is made from the HTTP headers of the request: the client can be served a different format, a different template, or different headers, or refused entirely.
The rules run on the panel side and never reach the nodes. Xray's own routing
(routing.rules) is set in the config profile and applied to nodes â see
Config profiles.
Where they are configuredâ
The rules are stored in the subscription settings as the responseRules object
and edited in the rule management section:
{
"version": "1",
"settings": { "disableSubscriptionAccessByPath": false },
"rules": []
}
disableSubscriptionAccessByPath: true closes access to the subscription via
additional paths (/json, /mihomo, /stash).
Order of applicationâ
Rules are checked top to bottom. The first matching rule fires, and the check
stops there. Rules with enabled: false are skipped. If no rule matches, the
request is blocked â that is why the last rule is often one without conditions
that serves the regular subscription.
Operators and conditionsâ
The rule's operator defines how conditions are combined:
| Operator | When the rule matches |
|---|---|
AND | all conditions match |
OR | at least one condition matches |
An empty conditions array always matches â this is the "default rule". Each
condition checks a single header:
{
"headerName": "user-agent",
"operator": "CONTAINS",
"value": "happ",
"caseSensitive": false
}
| Condition operator | Check |
|---|---|
EQUALS, NOT_EQUALS | exact match |
CONTAINS, NOT_CONTAINS | substring occurrence |
STARTS_WITH, NOT_STARTS_WITH | start of the string |
ENDS_WITH, NOT_ENDS_WITH | end of the string |
REGEX, NOT_REGEX | regular expression |
Header names are case-insensitive, several values of the same header are joined with a comma, and a missing header means the condition is not met.
Response typesâ
responseType determines what the client receives on a match:
| Type | Response |
|---|---|
XRAY_JSON, XRAY_BASE64, MIHOMO, CLASH, STASH, SINGBOX | the subscription in the required format |
BROWSER | an HTML page for the browser |
BLOCK | refusal, HTTP 403 |
STATUS_CODE_404, STATUS_CODE_451 | refusal with code 404 or 451 |
SOCKET_DROP | connection drop |
Response modificationsâ
The responseModifications block refines the response:
subscriptionTemplateâ the template name; it takes priority over external squad settings;headersandapplyHeadersToEndâ add headers, at the very end if needed, on top of the others;ignoreHostXrayJsonTemplateâ do not use the host's Xray JSON template;ignoreServeJsonAtBaseSubscriptionâ serve base64 even to clients that are normally served JSON;disableHwidCheckâ do not check HWID for this rule;additionalExtendedClientsRegexâ extend the list of "extended" clients;excludeHostsByTagsâ remove hosts with the specified tags from the output;respondWithRemarksâ replace the response body with text.
A typical scenario: serve Android clients a separate JSON template, and legacy
apps â BLOCK. The panel shows an example of such a rule when editing.
A rule without conditions and with responseType: BLOCK will block everyone who
reaches it. Order rules from most to least specific and check the subscription
after every edit.
What's nextâ
- Templates â what is inserted into the response.
- Squads â the priority of rules over external squads.
- Hosts â host tags for
excludeHostsByTags. - Config profiles â Xray routing on nodes.