Files
RustProxy/docs/CUSTOM_LOCATIONS.md
T
2026-10-04 22:53:33 +02:00

103 lines
6.8 KiB
Markdown

# Custom locations
RustProxy 0.22.3 supports the common location-level controls that are typically used for application reverse proxies. The UI intentionally exposes a safe subset instead of accepting arbitrary Nginx configuration text.
## Routing model in 0.16.0
The vhost's main backend pool is an internal fallback and is **not** one of the Custom locations. Custom locations are optional overrides only. Request routing is therefore:
```text
exact custom location
-> priority/regex/prefix custom location according to the documented precedence
-> main vhost backend pool
```
An empty Custom locations list is valid. Adding `/test`, a regex, a local response or a dedicated-backend location cannot disable `/`, `/abc` or other unmatched paths. Older saved documents that contain the former untouched synthetic `root` prefix `/` entry are normalized automatically. If `/` was deliberately customized with a backend, cache/ACL/header rule, rewrite or local response, it remains a real Custom location and intentionally overrides the main fallback.
## Dashboard editor
The visual editor is the primary workflow. Every location card now shows a live **Effective behavior preview** at the bottom with the match mode/pattern, proxy or local-response action, selected backend, rewrite behavior, cache policy, ACL composition and request/response header-rule counts. The preview is calculated from the unsaved form state so an administrator can verify intent before saving.
Request and response header rules use numbered visual cards with localized **Operation / Header name / Header value** controls. `Set`, `Append` and `Remove` are supported. The Advanced JSON view remains available for automation/copy-paste, but is no longer required for normal editing. The documentation button in the location tab explains precedence, rewrites, local responses, policy composition and common examples.
## Match modes
Each location has an ID, a pattern and one match mode:
| RustProxy mode | Nginx-style equivalent | Behaviour |
| --- | --- | --- |
| `prefix` | `location /path/` | Longest matching path prefix. A matching regex may still win. |
| `prefix_priority` | `location ^~ /path/` | Longest prefix and, when selected, skips regex locations. |
| `exact` | `location = /path` | Exact normalized path only. Exact matches have highest priority. |
| `regex` | `location ~ pattern` | Case-sensitive Rust regular expression. Regex locations are tested in configuration order. |
| `regex_insensitive` | `location ~* pattern` | Case-insensitive Rust regular expression. Regex locations are tested in configuration order. |
Routing and ACL checks collapse repeated literal slashes, matching Nginx's usual `merge_slashes on` behaviour. For example `/static/js//events.js` is routed as `/static/js/events.js`. Unless a rewrite is configured, the original request target is still sent to the backend.
Encoded separators (`%2f`, `%5c`), encoded `%`, dot segments and other ambiguous path forms are still rejected instead of being silently normalized.
## Actions
A location can proxy to a backend, serve an existing Web Service, or return a local response.
### Proxy
The location can use the vhost pool or pin traffic to one backend. A dedicated backend can be created from the location editor. Cache policy can inherit from the vhost or be explicitly enabled/disabled for the location.
Supported path transformations:
- **Preserve** — send the original client path unchanged.
- **Strip prefix** — remove the matched prefix before proxying.
- **Replace prefix** — replace the matched prefix with another normalized path prefix.
- **Regex rewrite** — available for regex locations; Rust regex captures can be referenced as `$1` or `${1}` in the replacement.
The query string is preserved. Rewrites change only the selected source path; reverse-proxy cache identity remains based on the public client URL.
### Web Server
`Web Server` selects one reusable service previously created in the **Web Server** workspace. The location stores only the Web Service ID; document root, index list and directory-listing policy remain in that shared service. Existing location matching and path rewriting are reused, but backend pinning and reverse-proxy object-cache controls do not apply to local files. See [WEB_SERVER.md](WEB_SERVER.md).
### Local response
`Return custom response` is the equivalent of a simple Nginx `return`: choose an HTTP status from 200 through 599, a Content-Type and a response body. RustProxy does not open a backend connection for this action. `HEAD`, `204` and `304` responses do not send a body.
For a redirect, use a 3xx status and add a `Location` response header in the visual header configurator.
## Request and response headers
Every location has a visual header configurator and an Advanced JSON view. Both edit the same data.
Supported operations are:
- `set` — replace the header with the configured value;
- `append` — append another header value;
- `remove` — remove the header.
Example JSON:
```json
{
"request": [
{"op": "set", "name": "X-App-Route", "value": "api"}
],
"response": [
{"op": "set", "name": "Cache-Control", "value": "no-store"},
{"op": "remove", "name": "X-Legacy-Header"}
]
}
```
Hop-by-hop/framing headers, forwarding identity headers, RustProxy request IDs and WebSocket handshake headers are protected and cannot be overwritten by custom rules. This prevents a location rule from changing transport framing or spoofing the verified client identity.
## Access control
A location can define its own IPv4/IPv6 CIDR ACL, select a reusable ACL profile, add a location-specific country block/allow-only rule, and configure an HTTP method policy (`off`, `allow` or `block`). Method names are normalized to uppercase and validated as HTTP method tokens.
All access layers are additive. The request must pass the vhost method policy, location method policy, host/profile/vhost IP ACLs, location profile ACL, inline location ACL and every applicable country policy. A location therefore cannot override a denial from its vhost. Method denial returns `405 Method Not Allowed` (with `Allow` for allow-list mode); IP/country denials retain the normal `403` pipeline. These checks occur before backend selection/connection.
Authentication, vhost rate limits, security headers, compression, custom error pages and WebSocket policy still apply through the normal vhost pipeline.
## What is intentionally not an Nginx parser
Custom locations do **not** execute arbitrary Nginx directives or configuration snippets. RustProxy does not currently implement location-level `try_files`, per-location filesystem aliases/roots, embedded scripting, arbitrary `if` expressions or arbitrary module directives. Static roots are defined only by reusable Web Services. Use the explicit UI controls and the documented JSON schema instead; unknown fields are rejected on save.