v0.29.2
This commit is contained in:
1 parent
76cb4acef0
commit
68678e98be
84 files changed
+1519
-325
No files matched your search
+1
-1
@@ -1,4 +1,4 @@
|
||||
# Administration API access - 0.29.0
|
||||
# Administration API access - 0.29.1
|
||||
|
||||
## Sign-in boundary
|
||||
|
||||
|
||||
+2
-2
@@ -9,7 +9,7 @@ each Docker host, so the proxy container never needs Docker-socket access. See
|
||||
Build locally with a normal OCI builder:
|
||||
|
||||
```bash
|
||||
docker build -t rustproxy:0.29.0 .
|
||||
docker build -t rustproxy:0.29.1 .
|
||||
```
|
||||
|
||||
Persist `/var/lib/rustproxy`; it contains the SQLite database, certificates and the
|
||||
@@ -22,7 +22,7 @@ docker volume create rustproxy-data
|
||||
docker run --rm -d --name rustproxy \
|
||||
-p 8080:8080 \
|
||||
-v rustproxy-data:/var/lib/rustproxy \
|
||||
rustproxy:0.29.0
|
||||
rustproxy:0.29.1
|
||||
|
||||
docker exec rustproxy rust-proxy admin setup-token
|
||||
```
|
||||
|
||||
@@ -110,6 +110,12 @@ All access layers are additive. The request must pass the vhost method policy, l
|
||||
|
||||
Authentication, vhost rate limits, security headers, compression, custom error pages and WebSocket policy still apply through the normal vhost pipeline.
|
||||
|
||||
## Internal locations and error fallbacks
|
||||
|
||||
RustProxy 0.29.1 can mark a Custom location as `internal`. An internal location is addressed by its stable location `id` and is never selected by a public URI match. The vhost main source or another Custom location can use `error_fallback` to internally dispatch configured `403/404/500/502/503/504` responses to that target. The default intercepted status is `404`.
|
||||
|
||||
This is an internal request handoff, not an HTTP redirect. The original method, URI/query and request context are retained. The fallback target re-enters normal access/header/cache/compression/response processing. Fallback targets must be enabled internal locations in the same vhost; validation rejects cycles and runtime dispatch is depth-limited. See [0.29.1 implementation note](V0.29.1_IMPLEMENTATION.md).
|
||||
|
||||
## 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.
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# Stored log explorer
|
||||
|
||||
RustProxy 0.29.0 provides an authenticated, read-only **Logs** workspace at `/logs`. The top bar has one **Logs** menu with separate **Stored logs** and **Live Logs** actions; the two data paths remain independent.
|
||||
RustProxy 0.29.1 provides an authenticated, read-only **Logs** workspace at `/logs`. The top bar has one **Logs** menu with separate **Stored logs** and **Live Logs** actions; the two data paths remain independent.
|
||||
|
||||
## Separation from Live Logs
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
# Installing and updating RustProxy 0.29.0
|
||||
# Installing and updating RustProxy 0.29.1
|
||||
|
||||
The scripts prepare a Linux/systemd installation. This source archive is **not a
|
||||
verified production build**: Rust/Cargo, real CA operations, live systemd startup
|
||||
|
||||
+39
-1
@@ -63,6 +63,7 @@ The normal ordered `index` list handles `index.php`; there is no separate PHP-in
|
||||
|
||||
### Additional PHP/FastCGI options
|
||||
|
||||
- `path_info`: default-off secure script/path splitting. When enabled, `/index.php/foo/bar` may resolve the existing `index.php` script and pass `/foo/bar` as `PATH_INFO`.
|
||||
- `pass_authorization`: forwards the inbound `Authorization` header as `HTTP_AUTHORIZATION`. Disable it when the application does not need that header.
|
||||
- `max_request_body_bytes`: streaming request-body limit enforced before/during FastCGI forwarding. `0` means no additional RustProxy-side limit. A request exceeding the configured value receives `413 Payload Too Large`.
|
||||
- `max_response_header_bytes`: maximum bytes accepted before the CGI response-header terminator. The allowed range is 4096..1048576 bytes.
|
||||
@@ -137,6 +138,7 @@ RustProxy supplies a controlled CGI/FastCGI parameter set including:
|
||||
- `REQUEST_METHOD`
|
||||
- `SCRIPT_FILENAME`
|
||||
- `SCRIPT_NAME`
|
||||
- `PATH_INFO` when `path_info` is enabled and a trailing path was securely split from an existing PHP script
|
||||
- `QUERY_STRING`
|
||||
- `REQUEST_URI`
|
||||
- `DOCUMENT_ROOT`
|
||||
@@ -157,7 +159,7 @@ Request headers cannot become FastCGI `PHP_VALUE` or `PHP_ADMIN_VALUE` parameter
|
||||
|
||||
An inbound `Proxy` header is **never** translated into FastCGI `HTTP_PROXY` (httpoxy mitigation), regardless of the optional Web Service hardening switch. The **Block common attack probes** option additionally blocks high-confidence sensitive/probe paths before PHP-FPM dispatch. FastCGI output cannot control downstream `Content-Length`, transfer framing, connection headers or `Proxy-*` transport headers; RustProxy owns downstream response framing.
|
||||
|
||||
`PATH_INFO` script/path splitting is not implemented in the current 0.25 development stage; applications should route explicitly to a real script, normally through `try_files`.
|
||||
`PATH_INFO` splitting is optional and disabled by default. When enabled, RustProxy searches for an existing configured PHP script prefix inside the document root, keeps `SCRIPT_FILENAME`/`SCRIPT_NAME` on that script, and supplies only the remaining suffix as `PATH_INFO`. `REQUEST_URI` remains the original request target.
|
||||
|
||||
## Response parsing
|
||||
|
||||
@@ -223,3 +225,39 @@ The implementation includes source/unit coverage for:
|
||||
- bounded endpoint/time/concurrency configuration validation.
|
||||
|
||||
Release-host acceptance should additionally exercise a real PHP-FPM runtime over Unix socket and loopback TCP and verify ACL/auth/custom errors/headers plus H1/H2/H3 client transports.
|
||||
|
||||
|
||||
## Per-Web-Service PHP administrative INI overrides (0.29.2)
|
||||
|
||||
`php.php_admin_values` is a validated operator-managed string map sent in a single
|
||||
`PHP_ADMIN_VALUE` FastCGI parameter. Example:
|
||||
|
||||
```json
|
||||
"php": {
|
||||
"enabled": true,
|
||||
"path_info": true,
|
||||
"endpoint": "unix:/run/php/php-fpm-mail.sock",
|
||||
"php_admin_values": {
|
||||
"open_basedir": "/var/www/webmail/:/tmp/",
|
||||
"display_errors": "Off"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Use separate Web Services for distinct per-location PHP settings, then assign those
|
||||
services to the corresponding Custom Locations. Each Web Service can refer to the
|
||||
same trusted PHP-FPM socket. The setting does **not** isolate worker process
|
||||
identities or file permissions. Never expose PHP-FPM FastCGI to untrusted clients.
|
||||
HTTP headers cannot supply `PHP_ADMIN_VALUE`, and `php_values` must not repeat
|
||||
an admin directive. Control characters and excessive values are rejected.
|
||||
|
||||
Prometheus metrics use only configured Web Service IDs, never script paths,
|
||||
URLs, PHP values, or dynamic user labels. `rust_proxy_php_requests_total` and
|
||||
`rust_proxy_php_responses_total{class=...}` count responses after headers have
|
||||
been received (including proxy-generated failures); the cumulative header
|
||||
latency metric intentionally excludes streamed body time.
|
||||
|
||||
The same snapshot also exports `rust_proxy_web_server_requests_total`,
|
||||
`rust_proxy_web_server_responses_total{class=...}` and
|
||||
`rust_proxy_web_server_response_header_duration_microseconds_total` for all
|
||||
Web Server requests (PHP and non-PHP).
|
||||
+2
-1
@@ -15,6 +15,7 @@ This is the canonical index for the current project documentation. The authentic
|
||||
- [0.25.1 release audit](V0.25.1_AUDIT.md) - historical Traffic/module-split release scope and compiler-regression guards.
|
||||
- [0.25.0 specification audit](V0.25.0_AUDIT.md) - Web Server foundation point-by-point implementation status.
|
||||
- [0.25.0 pre-production security audit](V0.25.0_SECURITY_PREPROD_AUDIT.md) - threat-oriented source/configuration review, fixes made in-session and mandatory runtime security gates.
|
||||
- [0.29.1 implementation note](V0.29.1_IMPLEMENTATION.md) - internal error fallbacks, multipart byte ranges and PHP PATH_INFO.
|
||||
- [0.29.0 implementation note](V0.29.0_IMPLEMENTATION.md) - canonical host/custom-location redirects, health Host defaults, forced cache and gzip Stored Logs.
|
||||
- [0.28.2 implementation note](V0.28.2_IMPLEMENTATION.md) - external certificate ACL/path hardening and least-privilege Certificate API grants.
|
||||
- [0.28.1 implementation note](V0.28.1_IMPLEMENTATION.md) - external certificate paths, Certbot symlink reloads, backup semantics and certificate-source UX.
|
||||
@@ -75,7 +76,7 @@ This is the canonical index for the current project documentation. The authentic
|
||||
|
||||
## Historical or version-labelled context
|
||||
|
||||
Version-labelled `V*.md` files are retained as historical implementation/audit records. Their version number describes the audited milestone. The current release implementation note is [V0.29.0_IMPLEMENTATION.md](V0.29.0_IMPLEMENTATION.md); [V0.28.2_IMPLEMENTATION.md](V0.28.2_IMPLEMENTATION.md) is retained as the prior certificate-hardening milestone; [V0.28.1_IMPLEMENTATION.md](V0.28.1_IMPLEMENTATION.md) is retained as the prior external-path milestone; [V0.28.0_IMPLEMENTATION.md](V0.28.0_IMPLEMENTATION.md) is retained as the prior GeoIP/listener/cache milestone, and [V0.27.3_IMPLEMENTATION.md](V0.27.3_IMPLEMENTATION.md) is retained as the prior HTTP/3/cache-maintenance milestone, [V0.27.2_IMPLEMENTATION.md](V0.27.2_IMPLEMENTATION.md) is retained as the prior managed-ACME repair, [V0.27.1_IMPLEMENTATION.md](V0.27.1_IMPLEMENTATION.md) as the prior managed-runtime/list-sorting milestone, and older version notes remain historical evidence. The latest retained audit is [V0.25.5_AUDIT.md](V0.25.5_AUDIT.md); older audit files remain available for traceability.
|
||||
Version-labelled `V*.md` files are retained as historical implementation/audit records. Their version number describes the audited milestone. The current release implementation note is [V0.29.1_IMPLEMENTATION.md](V0.29.1_IMPLEMENTATION.md); [V0.29.0_IMPLEMENTATION.md](V0.29.0_IMPLEMENTATION.md) is retained as the prior redirect/health/cache/log milestone; [V0.28.2_IMPLEMENTATION.md](V0.28.2_IMPLEMENTATION.md) is retained as the prior certificate-hardening milestone; [V0.28.1_IMPLEMENTATION.md](V0.28.1_IMPLEMENTATION.md) is retained as the prior external-path milestone; [V0.28.0_IMPLEMENTATION.md](V0.28.0_IMPLEMENTATION.md) is retained as the prior GeoIP/listener/cache milestone, and [V0.27.3_IMPLEMENTATION.md](V0.27.3_IMPLEMENTATION.md) is retained as the prior HTTP/3/cache-maintenance milestone, [V0.27.2_IMPLEMENTATION.md](V0.27.2_IMPLEMENTATION.md) is retained as the prior managed-ACME repair, [V0.27.1_IMPLEMENTATION.md](V0.27.1_IMPLEMENTATION.md) as the prior managed-runtime/list-sorting milestone, and older version notes remain historical evidence. The latest retained audit is [V0.25.5_AUDIT.md](V0.25.5_AUDIT.md); older audit files remain available for traceability.
|
||||
|
||||
Older context documents such as [INTEGRATIONS_040](INTEGRATIONS_040.md), [MANAGEMENT](MANAGEMENT.md), [SECURITY_AUDIT](SECURITY_AUDIT.md), [ACME_RFC2136](ACME_RFC2136.md) and older version audits remain available for traceability but should not override the current functional/technical documents above.
|
||||
|
||||
|
||||
+23
-75
@@ -1,87 +1,35 @@
|
||||
# Verification report - RustProxy 0.29.0
|
||||
# Verification report - RustProxy 0.29.2
|
||||
|
||||
## Scope
|
||||
## Changes
|
||||
|
||||
This report records verification of the 0.29.0 release source in the packaging environment. The release adds canonical www/non-www redirects, first-class Custom location redirects, automatic HTTP health-check Host selection, per-vhost forced-cache targets, bounded gzip log reading, and regression coverage for 503 maintenance pages and nested URL query strings. SQLite remains schema 9 and Cold Cache remains format 3.
|
||||
Same-version 0.29.2 correction: Web Server main routes no longer inherit `transient_unavailable` from the vhost backend configuration. When the Web Server source has no enabled Reverse Proxy Custom Locations, backend definitions are not compiled. An enabled reverse-proxy Custom Location still compiles and uses the backend pool. Removed fallback-only Prometheus metrics, retained PHP/Web Server metrics.
|
||||
|
||||
## Source and release checks
|
||||
Validated operator-controlled PHP_ADMIN_VALUE FastCGI configuration per Web Service,
|
||||
with distinct PHP_VALUE/ADMIN directive sets, explicit panel controls and OpenAPI
|
||||
schema. Prometheus PHP Web Service request/status counters, response header
|
||||
latency and available concurrency permit gauge, plus Web Server
|
||||
service-scoped response statuses and header latency.
|
||||
|
||||
The repository release gates are executed with:
|
||||
## Acceptance limitations
|
||||
|
||||
```bash
|
||||
./dev.sh test
|
||||
./dev.sh check
|
||||
```
|
||||
The build environment has no Rust compiler (`cargo`/`rustc`). Rust compilation,
|
||||
unit tests, FastCGI integration with a live PHP-FPM pool and runtime load tests
|
||||
have not been performed here. Rust-independent checks are recorded separately.
|
||||
This source package is not certified for production deployment.
|
||||
|
||||
`./dev.sh test` runs the Rust-independent source/module, release-smoke, memory, Web Server, security, dependency, browser-UI, documentation and translation checks before attempting Cargo. The 0.29.0 source checks cover the new configuration/UI/runtime contracts as well as retained release behavior.
|
||||
## Checks performed
|
||||
|
||||
Additional syntax checks used for the edited browser assets are:
|
||||
- Same-version correction: `python3 tools/checks/check_source.py` and `python3 tools/checks/release_smoke.py` passed. `bash ./dev.sh test` passed the Rust-independent checks and stopped at missing Rust/Cargo (exit 127). No live 503 regression test or Rust compilation could be performed.
|
||||
|
||||
```bash
|
||||
node --check src/admin/web/vhosts/core.js
|
||||
node --check src/admin/web/vhosts/editor.js
|
||||
node --check src/admin/web/vhosts/render.js
|
||||
```
|
||||
- `./dev.sh test`: all Rust-independent release, upgrade, security, JS, UI, documentation and source checks passed; exited 127 at the missing `cargo` toolchain guard.
|
||||
- `node --check src/admin/web/web-server.js`: passed.
|
||||
- `python -m json.tool src/admin/openapi.json`: passed.
|
||||
- `./dev.sh check`: exited 127 because Rust/Cargo is unavailable.
|
||||
|
||||
## Environment limitation
|
||||
## Debian deployment maintenance (same 0.29.2)
|
||||
|
||||
Rust/Cargo is not installed or not available on PATH in this packaging environment. Therefore Rust parsing, type checking, linking and execution of `cargo test --locked --all-targets` cannot be claimed here. `./dev.sh test` was executed and all Rust-independent gates printed PASS before the script stopped at the explicit Rust/Cargo guard with exit 127. `./dev.sh check` was also executed and stopped at the same guard with exit 127.
|
||||
Installer/update now installs /etc/logrotate.d/rustproxy using the recorded service user/group. Updates repair /etc/profile.d/rustproxy-path.sh rather than warning. logrotate uses copytruncate because RustProxy holds open log descriptors; some log records may be lost during truncate. Rust build and live Debian/systemd acceptance remain unverified in this environment.
|
||||
|
||||
## Version identity (0.29.2 source maintenance)
|
||||
|
||||
Observed auxiliary checks:
|
||||
|
||||
```text
|
||||
node --check src/admin/web/vhosts/core.js PASS
|
||||
node --check src/admin/web/vhosts/editor.js PASS
|
||||
node --check src/admin/web/vhosts/render.js PASS
|
||||
(cd docker-agent && go test ./...) PASS
|
||||
```
|
||||
|
||||
An attempt to fetch a user-local Rust toolchain was unavailable from this environment, so no compiler result is inferred from the source/static checks.
|
||||
|
||||
A Rust-enabled release host must still run:
|
||||
|
||||
```bash
|
||||
cargo fmt --all -- --check
|
||||
cargo check --locked --all-targets
|
||||
cargo test --locked --all-targets
|
||||
```
|
||||
|
||||
before promoting the binary package.
|
||||
|
||||
## Functional regressions included in source
|
||||
|
||||
The Rust test source includes coverage for:
|
||||
|
||||
- www/non-www companion routing and canonical redirect behavior;
|
||||
- default and explicitly overridden HTTP health-check Host selection;
|
||||
- Custom location redirects with a separate capture regex and query preservation;
|
||||
- per-vhost forced-cache target matching and retained protocol-safety exclusions;
|
||||
- bounded discovery/read of rotated `.gz` Stored Logs;
|
||||
- a static/maintenance HTML response with HTTP 503;
|
||||
- preservation of a valid nested-URL query string in the upstream URI.
|
||||
|
||||
Literal/encoded backslashes remain intentionally rejected by the ambiguous-routing guard. For the reported curl case, use normal query separators inside a quoted URL rather than `\?`, `\=` or `\&`.
|
||||
|
||||
## Post-release source revision: multi-host vhost and canonical selector
|
||||
|
||||
The vhost editor now selects a canonical hostname from the configured host list, with a legacy first-host fallback. An additional Rust regression test verifies independent `suba.local` and `subb.local` aliases and a selected redirect target; invalid foreign redirect targets are rejected. Compiler/runtime tests remain unverified in this environment.
|
||||
|
||||
## Frontends WWW-routing UX revision
|
||||
|
||||
The editor groups host chips and WWW redirect controls in the same Frontends tab. The legacy select is replaced by accessible paired radio choices showing both `www -> bare` and `bare -> www` for each exact host (also while the feature is off), plus a list of non-redirected aliases and the number of configured names. A `www.` destination can be implicit: routing claims both hosts even if only the bare name was listed in the vhost. Wildcards are not offered as redirect targets. The selected target survives unrelated edits and automatically falls back to a valid hostname when removed; wildcard-only configurations disable the redirect control and show guidance. The persisted fields (`www_redirect` and `www_redirect_target`) are unchanged.
|
||||
|
||||
`node tools/checks/vhost_www_ui_test.mjs` runs the actual WWW-routing editor component in a DOM stand-in and covers its switch, selected-target restore, alias visibility, both redirect directions, implicit `www.` target, wildcard handling, removal fallback, and serialization. Rust source includes a complementary runtime regression for the implicit www routing pair. These checks do not substitute for executing Rust proxy runtime tests.
|
||||
|
||||
## WWW UX correction (source revision)
|
||||
|
||||
The Frontends tab now shows the WWW target choices next to its hostname editor, grouped by domain and available for preview even when the feature is disabled. Both www to bare and bare to www destinations are available. A WWW destination may be implicit (`www.subb.local` with only `subb.local` configured); the runtime claims both hostnames for the selected pair, while a second domain (`suba.local`) remains an independent alias of the same vhost and backend. A Rust regression test covers the implicit WWW direction; static checks and JS syntax tests are described above. Full Rust compiler/runtime verification still requires Cargo.
|
||||
|
||||
### WWW UX packaging verification
|
||||
|
||||
In this source revision, `node tools/checks/www_redirect_ui_test.mjs` and
|
||||
`node tools/checks/vhost_www_ui_test.mjs` both pass their DOM-stand-in selection
|
||||
and synchronization checks. `./dev.sh test` passed all pre-Cargo checks and
|
||||
stopped at the missing Cargo guard with exit 127. Syntax checks for the edited
|
||||
JavaScript and the two language JSON packs also passed. This does not establish
|
||||
Rust compile/test success or end-to-end browser behavior.
|
||||
`Cargo.toml` package version is the canonical release identity. Rust uses `CARGO_PKG_VERSION` at build time; `build.rs` substitutes the admin HTML placeholder. Packaging, upgrade and dev scripts read the manifest with `scripts/version.py`. Run `python3 tools/checks/version_contracts.py` to check that executable paths do not hardcode a version. Historical documentation and external dashboards may retain manually managed versions. Rust compilation/runtime verification is still pending.
|
||||
@@ -0,0 +1,127 @@
|
||||
# RustProxy 0.29.1 implementation note
|
||||
|
||||
RustProxy 0.29.1 adds explicit Nginx-style internal error routing without parsing Nginx configuration, plus multipart byte ranges and optional PHP `PATH_INFO` support. SQLite remains schema 9 and Cold Cache remains format 3.
|
||||
|
||||
## Internal error fallback
|
||||
|
||||
A vhost main source and each Custom location can define:
|
||||
|
||||
```json
|
||||
"error_fallback": {
|
||||
"target": "redirect-check",
|
||||
"statuses": [404]
|
||||
}
|
||||
```
|
||||
|
||||
`target` is the stable `id` of an enabled Custom location in the same vhost with `"internal": true`. Internal locations are retained in the compiled route table but never participate in normal public URI matching. The supported intercepted status set is deliberately bounded to `403`, `404`, `500`, `502`, `503` and `504`; omitting `statuses` defaults to `404`.
|
||||
|
||||
The dispatch is internal, not a `3xx` client redirect. RustProxy rebuilds the fallback request with the original HTTP method, URI, query string, HTTP version, request headers and the existing transport/request context. The target location then executes through the normal vhost/location path, including ACL/authentication, header rules, cache policy, compression and response processing. Vhost rate limiting is not charged a second time for the same client request.
|
||||
|
||||
For requests with a body, RustProxy can replay a body only when its exact size is known and no larger than 8 MiB. Such a request is buffered once so the same bytes can be sent to the fallback target. Unknown-size or larger streaming bodies continue to the original target, but an error fallback cannot replay them; the original error response is retained.
|
||||
|
||||
Configuration validation rejects missing/public fallback targets and recursive fallback cycles. A runtime depth limit of 8 internal dispatches remains as a second guard against loops after hot-reload/state inconsistencies.
|
||||
|
||||
Configured upstream response statuses are intercepted before normal response finalization and cache publication. RustProxy-generated reverse-proxy failures also participate where applicable: missing backend (`500`), unavailable/capacity (`503`), connect failure (`503`), invalid upstream response (`502`) and response timeout (`504`). A configured stale cached response still wins before transport-error fallback.
|
||||
|
||||
## Example: static files -> application -> redirector
|
||||
|
||||
The following vhost fragment expresses the same request flow as an Nginx `try_files`/`error_page` chain, without an HTTP redirect between stages:
|
||||
|
||||
```json
|
||||
{
|
||||
"source": {
|
||||
"type": "web_server",
|
||||
"web_service_id": "www-linuxiarz"
|
||||
},
|
||||
"error_fallback": {
|
||||
"target": "to8000",
|
||||
"statuses": [404]
|
||||
},
|
||||
"backends": [
|
||||
{
|
||||
"id": "app",
|
||||
"url": "http://127.0.0.1:8000",
|
||||
"enabled": true,
|
||||
"allow_private": true,
|
||||
"address_allowlist": ["127.0.0.1/32"]
|
||||
},
|
||||
{
|
||||
"id": "redirector",
|
||||
"url": "http://127.0.0.1:9000",
|
||||
"enabled": true,
|
||||
"allow_private": true,
|
||||
"address_allowlist": ["127.0.0.1/32"]
|
||||
}
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"id": "to8000",
|
||||
"internal": true,
|
||||
"backend_id": "app",
|
||||
"source": {"type": "reverse_proxy"},
|
||||
"error_fallback": {
|
||||
"target": "redirect-check",
|
||||
"statuses": [404]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "redirect-check",
|
||||
"internal": true,
|
||||
"backend_id": "redirector",
|
||||
"source": {"type": "reverse_proxy"},
|
||||
"cache": false
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The effective flow is:
|
||||
|
||||
```text
|
||||
public request
|
||||
-> Web Server
|
||||
2xx/3xx -> return normally
|
||||
404 -> @to8000 (internal)
|
||||
-> backend app
|
||||
non-404 -> return normally
|
||||
404 -> @redirect-check (internal)
|
||||
-> redirector backend
|
||||
```
|
||||
|
||||
Normal public Custom locations can still route `/stats`, `/user-info`, `/health`, RBL files or other paths directly before the main source is used. An internal location's `path_prefix` is not used for public matching; its `id` is the fallback name.
|
||||
|
||||
## Multipart byte ranges
|
||||
|
||||
The Web Server now accepts comma-separated byte ranges such as:
|
||||
|
||||
```http
|
||||
Range: bytes=0-99,200-299
|
||||
```
|
||||
|
||||
One satisfiable range retains the existing single-part `206` response. Multiple satisfiable ranges produce a streaming `multipart/byteranges` response with per-part `Content-Type` and `Content-Range`. At most 16 ranges are accepted. Malformed or entirely unsatisfiable range sets return `416`. Multipart responses use the identity file representation rather than `.br`/`.gz` sidecars so the multipart MIME framing and `Content-Encoding` semantics cannot conflict.
|
||||
|
||||
## PHP PATH_INFO
|
||||
|
||||
Web Service PHP configuration gains the default-off field:
|
||||
|
||||
```json
|
||||
"php": {
|
||||
"enabled": true,
|
||||
"path_info": true
|
||||
}
|
||||
```
|
||||
|
||||
When enabled, RustProxy may resolve a request such as `/index.php/foo/bar` by finding the longest existing configured PHP script prefix under the Web Service document root. FastCGI then receives, conceptually:
|
||||
|
||||
```text
|
||||
SCRIPT_FILENAME=/document/root/index.php
|
||||
SCRIPT_NAME=/index.php
|
||||
PATH_INFO=/foo/bar
|
||||
REQUEST_URI=/index.php/foo/bar
|
||||
```
|
||||
|
||||
The split uses the same document-root confinement and PHP file checks as normal script resolution. It is disabled by default because it changes URL-to-script resolution semantics.
|
||||
|
||||
## Compatibility
|
||||
|
||||
No SQLite migration is required. Existing vhosts, locations and Web Services deserialize unchanged because `internal`, `error_fallback` and PHP `path_info` use backward-compatible defaults. Existing single-range responses are retained.
|
||||
@@ -38,6 +38,12 @@ health/traffic history. Because the vhost configuration participates in cache co
|
||||
a rename also rotates that compatibility identity and invalidates incompatible cached objects.
|
||||
The editor warns before applying the rename.
|
||||
|
||||
## Internal error routing
|
||||
|
||||
The main vhost `source` may define `error_fallback`, and each Custom location may do the same. A fallback references the `id` of an enabled `internal` Custom location in the same vhost. Supported statuses are `403`, `404`, `500`, `502`, `503` and `504`; omitted status lists default to `404`. Internal targets are not reachable by ordinary path matching.
|
||||
|
||||
Configured upstream/Web Server failures are intercepted before final response/cache publication. The original request method, URI/query and context are internally dispatched to the target, which then follows normal vhost/location processing. Validation rejects fallback cycles and runtime dispatch is depth-limited. See [V0.29.1_IMPLEMENTATION.md](V0.29.1_IMPLEMENTATION.md) for body replay bounds and an Nginx-style static -> app -> redirector example.
|
||||
|
||||
## Frontend selection and private IP isolation
|
||||
|
||||
`frontend.hosts` is a normalized hostname-pattern list. Exact hostnames and a single
|
||||
|
||||
+5
-4
@@ -217,20 +217,21 @@ Optional precompressed delivery checks sidecar files only after the original res
|
||||
|
||||
The client must advertise the matching coding in `Accept-Encoding`. Brotli is preferred when both are available. The response keeps the original file's MIME type and adds the appropriate `Content-Encoding` and `Vary: Accept-Encoding`.
|
||||
|
||||
Validators, streaming and a single Range request operate on the selected representation. RustProxy does not compress the file on every request in this mode.
|
||||
Validators, streaming and a single Range request operate on the selected representation. Multipart Range responses use the identity representation so MIME boundaries are never mixed with a precompressed sidecar. RustProxy does not compress the file on every request in this mode.
|
||||
|
||||
## Range and downloads
|
||||
|
||||
Static and precompressed responses support:
|
||||
Static responses support:
|
||||
|
||||
- single `Range: bytes=...`;
|
||||
- multipart `Range: bytes=0-99,200-299` with at most 16 ranges;
|
||||
- `If-Range`;
|
||||
- `206 Partial Content`;
|
||||
- `416 Range Not Satisfiable`;
|
||||
- `Accept-Ranges` and `Content-Range`;
|
||||
- `Accept-Ranges` and per-part `Content-Range`;
|
||||
- streaming rather than whole-file buffering.
|
||||
|
||||
Multipart ranges remain intentionally unsupported.
|
||||
Single ranges can operate on a selected precompressed representation as before. Multipart ranges intentionally use the identity representation and stream `multipart/byteranges`.
|
||||
|
||||
Configured `download_extensions` add `Content-Disposition: attachment` using an encoded filename. This is useful for storage/download services without changing the MIME type.
|
||||
|
||||
|
||||
Reference in new issue
Block a user