Skip to content

feat: add PUT /rules to replace rules without reloading the whole config - #3373

Open
SpectreAX wants to merge 1 commit into
MetaCubeX:Alphafrom
SpectreAX:feat/apply-rules
Open

SpectreAX wants to merge 1 commit into
MetaCubeX:Alphafrom
SpectreAX:feat/apply-rules

Conversation

@SpectreAX

Copy link
Copy Markdown

What

Adds PUT /rules, which replaces the rules, sub-rules and rule providers of a running core without reloading anything else.

It takes the same body as PUT /configs:

PUT /rules
{"payload": "<full config yaml>"}   // or {"path": "/abs/path/config.yaml"}, or {} for the current config file

Only rules, sub-rules and rule-providers from that config are applied, through a new executor.ApplyRules. Proxies, groups and their selections, DNS, listeners and TUN keep running, and the tunnel is not suspended.

Why

Clients that edit routing at runtime, for example "send this domain to that group", currently have to PUT /configs. That rebuilds every proxy, DNS and listener, and suspends the tunnel to change a few rule lines. PATCH /rules/disable can only turn existing rules on and off; it cannot add, reorder or retarget them.

Details

  • Rule providers are loaded before the swap. Parsing creates them empty. Swapping them in unloaded would leave every RULE-SET rule matching nothing until the next full reload. ApplyRules calls the existing loadProvider first, with the same semantics as ApplyConfig: a provider that fails to load is logged, and the update still goes ahead.
  • Rules must target running proxies. The tunnel silently skips a rule whose proxy is missing, so a rule that targets a proxy or group that is not running is rejected with 400, and nothing changes. Adding proxies still needs PUT /configs.
  • ApplyRules holds the same lock as ApplyConfig.
  • The request parsing in updateConfigs moves into parseConfigRequest, so both endpoints share the same payload / path / safe-path handling. PUT /configs behaves as before.
  • Like PUT /configs and PATCH /rules/disable, PUT /rules is not registered in embed mode.

Testing

  • New hub/executor/apply_rules_test.go:
    • RULE-SET rules keep matching after ApplyRules. This test fails if the provider loading is removed.
    • A rule targeting a group that is not running is rejected, and the running rules stay as they were.
  • go test ./hub/... ./config/... ./rules/..., go vet with Go 1.20 and 1.27, and cross-builds for linux, windows and android.
  • Ran a binary built from this branch with a real VLESS Reality node and sent HTTPS traffic through the mixed port:
    • PUT /rules switched a domain between DIRECT and the node by a RULE-SET, by the node's own name (emoji and | included), and back.
    • A rule to a group that is not running returned 400 … proxy [Netflix] is not running …, with traffic unaffected.
    • Invalid YAML and relative paths returned 400, and {} reloaded the rules from the config file.
    • PUT /configs still worked.
    • 4 clients kept requesting through 20 PUT /rules calls that alternated the route: no request failed, and both routes were used.

The API docs live in MetaCubeX/Meta-Docs. I can open a matching docs PR there if this is accepted.

🤖 Generated with Claude Code

PUT /rules takes the same body as PUT /configs (payload, or path, or
neither for the current config file) but applies only the rules,
sub-rules and rule providers, through the new executor.ApplyRules.
Proxies, DNS, listeners and TUN keep running and are not suspended.

Rule providers are loaded before the new rules take effect; parsing
creates them empty, so swapping them in unloaded would leave every
RULE-SET rule matching nothing. A rule that targets a proxy or group
which is not running is rejected with 400 and nothing changes, because
the tunnel would otherwise skip it silently. Like the other write
endpoints, PUT /rules is not available in embed mode.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant