4.3 KiB
RustProxy 0.28.0 implementation note
Scope
0.28.0 extends the 0.27.3 maintenance release with operator-controlled GeoIP refresh, clearer listener status, cache Via metadata, narrower cache invalidation and a vhost Security header-rule layout repair. SQLite schema 8 and COLD cache format 3 are unchanged.
GeoIP manual refresh and hot reload
POST /api/geoip/update is an authenticated/CSRF-protected control-plane action used by Settings -> GeoIP updates -> Download now. It invokes the same updater function as the background worker. The updater consumes direct source URLs, with optional publisher SHA-256 URLs per file, streams payloads into a private staging directory under the configured size limit, validates the selected database format, publishes only content whose local SHA-256 changed, and replaces the in-memory database only after validation succeeds. The UI action works when scheduled updates are disabled.
CSV mode uses separate IPv4 and IPv6 range files. MMDB mode uses one native MaxMind DB for both families and recognizes standard country.iso_code / registered_country.iso_code records plus a top-level country_code compatibility record or a root two-letter country string. The combined sapics user-country.mmdb is the default MMDB source. When the publisher checksum URL is empty, no remote checksum is required; structural validation and local content hashing remain mandatory. An updater-disabled MMDB configuration may leave the URL empty and manage <data-dir>/geoip/country.mmdb locally; the manual action then validates/reloads that local file.
The automatic worker, manual UI action and managed upgrade path serialize through .geoip-update.lock. Publishing uses the application's existing ArcSwap<Database>: a request that already owns the prior Arc remains memory-safe, while subsequent lookups load the new database. The request path uses this slot for country access rules, country rate limiting and optional country logging; administration and Prometheus status read the same slot. No process restart is needed.
Listener status UX
Settings no longer compresses active endpoints into one HTTP ... | HTTPS ... sentence. Each active endpoint is rendered as a separate compact card with protocol and address plus badges for the protocols that are actually enabled on the running listener: H1 is always present, TLS listeners add H2 when ALPN HTTP/2 is enabled and H3/UDP when QUIC is enabled, while cleartext listeners add H2C when prior-knowledge HTTP/2 is enabled. Saved-listener restart semantics are unchanged.
Cache Via and invalidation
cache.via_header is an optional string. Its default is RustProxy, producing Via: RustProxy; null disables RustProxy's Via value. Existing upstream Via fields are preserved and RustProxy appends its value. Validation bounds the configured field value to 256 valid HTTP-header bytes.
Cache compatibility hashing now normalizes request-only bypass fields and response-only cache diagnostics (X-Cache, hit counters, Cache-Status, resident age and Via). These changes apply on subsequent requests without discarding HOT/COLD objects. Representation/origin-affecting configuration remains in the compatibility identity and continues to invalidate incompatible objects.
Vhost Security header rules
The request/response header-rule editor now uses the same structured header editor layout as location rules. Delete is contained in the rule heading and aligned to the right, while Operation, Name and Value remain in the field grid below it.
Compatibility
- SQLite schema: 8, unchanged.
- COLD cache format: 3, unchanged.
- Existing saved configurations remain valid because
Settingsuses serde defaults; an absentcache.via_headerbecomesRustProxy. - Legacy 0.27.3 release/checksum base URLs are accepted during configuration migration. The old default checksum base migrates to optional/no publisher checksum; custom legacy bases are translated into per-file URLs.
Startup ACME runtime reporting
The human-readable startup banner no longer prints the initial checking/preparing ACME Python state, because that value can race the asynchronous runtime probe. When the probe finishes, RustProxy emits an INFO event named ACME runtime check complete containing the final status, mode, Python/pip/Certbot availability and managed-environment path.