# Python-only mock origin Run independently of Cargo/Rust, in a separate terminal: ```bash bash dev.sh mock --port 9001 --name origin-a --ttl 30 ``` This runs until Ctrl+C. A second origin for balancing uses another terminal: ```bash bash dev.sh mock --port 9002 --name origin-b --ttl 30 ``` The helper binds 127.0.0.1 by default. It accepts IPv4 addresses only and refuses non-loopback bindings without --allow-remote. Do not expose it publicly: /control deliberately has no authentication. It has 32 connection workers, 15-second socket timeout, a 2 MiB maximum response and a 10-second delay ceiling. It is a development fixture, not a secure production website. ## Configure a test vhost After building and starting RustProxy, create a vhost with domain mock.localhost, frontend 127.0.0.1:8080, backend http://127.0.0.1:9001, private backend permission, HTTP health path /health, and Cache enabled with X-Cache diagnostics. Leave sticky cookies off to test shared cache. Wait for its backend to become healthy. `examples/mock-vhost.json` is a complete ready-to-apply document for a disposable installation. It explicitly enables the per-vhost cache (the 0.8.1 global default is also enabled), adds a custom 503 page, and serves the congratulations page on direct-IP access. Applying it replaces all existing routes/vhosts; it is not a merge patch. Review first: ```bash bash dev.sh config validate examples/mock-vhost.json bash dev.sh config apply examples/mock-vhost.json ``` Do not replace your real configuration for this demonstration. Use the panel to add equivalent settings to an existing project instead. ## Verify cache, not just the origin Requests must go through the proxy with the right Host: ```bash curl -si -H 'Host: mock.localhost' http://127.0.0.1:8080/cache curl -si -H 'Host: mock.localhost' http://127.0.0.1:8080/cache ``` After the first complete response, expect MISS then HIT with an identical nonce while fresh. Origin JSON always generates a new nonce and timestamp; a cache hit therefore makes reuse visible. Health probes can advance the sequence too, so compare nonce/body, not an assumption that sequence increases by exactly one. GET is the clearest fill test because it consumes the complete body. HEAD is also cacheable in 0.11.5 and shares the GET representation. Only response `Vary` fields create request-header representation variants; unrelated request headers and the selected backend-pool member no longer fragment the same Host + URL object. Use the host's Purge action and request again to expect a new MISS. Waiting past TTL also refreshes. To compare with a non-cacheable route: ```bash curl -si -H 'Host: mock.localhost' http://127.0.0.1:8080/nocache curl -si -H 'Host: mock.localhost' http://127.0.0.1:8080/nocache ``` Bodies should change and must not become HIT. A diagnostic MISS means lookup was attempted, not that the response was stored: no-store/private/Set-Cookie may reject storage after origin headers arrive. BYPASS indicates a request-side exclusion. ## Endpoints | Path | Behavior | |---|---| | / | Small HTML page with links | | /cache?ttl=30 | Random JSON; public max-age; Vary: Accept-Language | | /nocache | Random JSON; no-store | | /private | Private JSON; cannot enter shared cache | | /cookie | Sets a cookie; must not enter shared cache | | /large?size=131072 | Compressible bytes; public freshness; useful above 65535 bytes | | /slow?ms=800 | Delayed no-store response | | /health | 200/503 according to controlled health; delay is also applied | | /state | Current health, delay, sequence and origin ID | | /status/401, /status/403, /status/404, /status/503 | Origin error responses for page tests; 401 includes a challenge | | POST /control | JSON with healthy:boolean and/or delay_ms:0..10000 | Compression needs enabled proxy compression and an appropriate Accept-Encoding. The origin itself does not compress. Inspect both response headers and decoded body; not all curl builds support Brotli or Zstandard. Example: ```bash curl -si --compressed -H 'Host: mock.localhost' \ 'http://127.0.0.1:8080/large?size=131072' ``` ## Failover, latency and recovery Control the origin directly, not through the proxy, especially after it is marked down. Configure the health path /health (the default root page always returns 200). ```bash curl -s -H 'Content-Type: application/json' -d '{"healthy":false}' http://127.0.0.1:9001/control curl -s -H 'Content-Type: application/json' -d '{"healthy":true,"delay_ms":1200}' http://127.0.0.1:9001/control curl -s -H 'Content-Type: application/json' -d '{"healthy":true,"delay_ms":0}' http://127.0.0.1:9001/control ``` Watch health/RTT in the vhost list/editor and dashboard. Fall/rise thresholds and probe interval delay transitions intentionally. Add origin-b as a second backend for failover and balancing tests. Random origin data alone does not prove that the Rust scheduler, compression or cache is correct; run the Rust acceptance tests. ## Verification scope The mock server is a development fixture, not a proxy test. Exercise its endpoints directly with curl when needed, then run the RustProxy suite separately with `bash dev.sh test` on a host that has Cargo.