Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,59 @@ Three forms are accepted: `tcp://host:port`, `http://...` and `https://...`.
> Readiness is polled only while the machine is live. A machine that sleeps all
> day therefore generates no per-route traffic.

## Static response cache

```toml
[cache]
enabled = true
root_path = "./cache"
ttl = "24h"
max_response_size_bytes = 10485760
warm_interval = "30m"

[[cache.routes]]
route = "files.home.com"
paths = ["/docs", "/assets/*"]
```

Some routes serve content that does not need the machine to be awake: a model
list, static assets, a landing page. With the cache enabled, a `GET` whose path
matches a configured pattern is served straight from disk when the machine is
offline, instead of waking it. The client gets a full answer while the box
stays asleep.

A `/*` suffix caches everything under a prefix (`/assets/*` covers
`/assets/app.css`). Only `GET` requests with a 2xx status are cached, and only
for routes named in `[[cache.routes]]`; responses larger than
`max_response_size_bytes` are skipped. The query string is part of the identity
of an entry, so `/models?filter=a` is stored and replayed separately from
`/models`.

Nothing that belongs to one client is ever stored, and nothing stored
anonymously is ever handed to an authenticated one: a request carrying an
`Authorization` or `Cookie` header is not cached and is not answered from cache
either, and neither is a response that sets a `Set-Cookie` or declares
`Cache-Control: private`, `no-store` or `no-cache`. A `Set-Cookie` header is
also dropped from anything that does get stored, so a cached page cannot hand
one visitor's session to the next.

The cache answers only for a machine the health checker has confirmed down. A
machine that is up but whose health entry has gone stale still serves its own
response.

The cache keeps itself warm: whenever a machine wakes up, and every
`warm_interval` while it stays up, the configured paths are re-fetched. A
response whose body has not changed is not rewritten, so a static file list
does not churn the disk. Entries older than `ttl` are dropped. Both `ttl` and
`warm_interval` must be positive - a zero or negative value is rejected as a
configuration error rather than expiring every entry or crashing the proxy at
startup.

> [!NOTE]
> Cached responses are replayed with the upstream headers they were stored
> with, minus framing headers. The proxy does not revalidate them against the
> machine, so pick a `ttl` that matches how stale the content may get.

## Idle shutdown

```toml
Expand Down
Loading