v0.29.2
This commit is contained in:
1 parent
76cb4acef0
commit
68678e98be
84 files changed
+1519
-325
No files matched your search
@@ -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.
|
||||
Reference in new issue
Block a user