Skip to content
Merged
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
6 changes: 6 additions & 0 deletions src/v3/features/cache-control-headers.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ A `max-age` of _one year_ is applied only to the following file types.
avif, bmp, bz2, css, doc, gif, gz, htc, ico, jpeg, jpg, js, jxl, map, mjs, mp3, mp4, ogg, ogv, pdf, png, rar, rtf, tar, tgz, wav, weba, webm, webp, woff, woff2, zip
```

> [!INFO] Error responses
>
> The file type `max-age` values apply only to successful (`2xx`) and `304 Not Modified` responses. Other file responses, such as a `404 Not Found` for a missing `/app.css`, get the `no-cache` directive.
>
> With a [fallback page](error-pages.md#fallback-page-for-use-with-client-routers) configured, a `GET` for a missing file is answered with `200 OK` and the fallback page, so it still gets the file type `max-age` value.

Below is an example of how to enable the feature.

```sh
Expand Down
51 changes: 48 additions & 3 deletions src/v3/features/custom-http-headers.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ outline: deep

The Server HTTP response headers should be defined mainly as an [Array of Tables](https://toml.io/en/v1.0.0#array-of-tables).

Each table entry should have two key/value pairs:
Each table entry should have the following key/value pairs:

- One `source` key containing a string _glob pattern_.
- One `headers` key containing a [set or hash table](https://toml.io/en/v1.0.0#table) describing plain HTTP headers to apply.
- An optional `status` key containing an array of HTTP response status codes.

A particular set of HTTP headers can only be applied when a `source` matches against the request URI.
A particular set of HTTP headers can only be applied when a `source` matches against the request URI and, if `status` is defined, the response status code is one of its values.

> [!INFO] Custom HTTP headers take precedence over existing ones
>
Expand All @@ -33,9 +34,21 @@ The source is a [Glob pattern](<https://en.wikipedia.org/wiki/Glob_(programming)

A set of valid plain [HTTP headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) to be applied.

### Status

An optional array of [HTTP response status codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) (numbers) that limits the entry to responses with one of those codes, for example `status = [200, 206, 304]`.

Without `status`, the headers apply regardless of the response status, including error responses like `404 Not Found`. This fits headers such as `Strict-Transport-Security`, but not caching headers: an `immutable` `Cache-Control` for `/assets/**` would also be sent with a `404` for a missing asset.

Custom headers are not added to responses that SWS returns before serving a file, such as [URL redirects](url-redirects.md), `405 Method Not Allowed` or maintenance mode responses, so a `status` of `301` or `503` never matches those.

To limit caching headers to successful file responses, include `304` next to `200` and `206`: a `304 Not Modified` updates the headers of the response stored by a cache ([RFC 9111, section 4.3.4](https://www.rfc-editor.org/rfc/rfc9111#section-4.3.4)).

SWS validates the codes at startup and fails to start on an empty array or a code outside `100` to `999`.

## Examples

Below are some examples of how to customize server HTTP headers in three variants.
Below are some examples of how to customize server HTTP headers.

### One-line version

Expand Down Expand Up @@ -69,3 +82,35 @@ Strict-Transport-Security = "max-age=63072000; includeSubDomains; preload"
source = "**/*.{jpg,jpeg,png,ico,gif}"
headers.Strict-Transport-Security = "max-age=63072000; includeSubDomains; preload"
```

### Limit headers to specific response status codes

```toml
[advanced]

[[advanced.headers]]
source = "/assets/**"
status = [200, 206, 304]
headers = { Cache-Control = "public, max-age=31536000, immutable" }
```

`GET /assets/app.css` returns `200 OK` with `cache-control: public, max-age=31536000, immutable`, while `GET /assets/missing.css` returns `404 Not Found` without the `immutable` directive.

> [!INFO] Fallback page
>
> With a [fallback page](error-pages.md#fallback-page-for-use-with-client-routers) configured, a `GET` for a missing file is answered with `200 OK` and the fallback page, so status filtering does not exclude it.

Entries apply in order and a later entry replaces a header set by an earlier one. Below, every `/assets/**` response gets `no-cache`, and the second entry replaces it with `immutable` for `200`, `206` and `304` responses only.

```toml
[advanced]

[[advanced.headers]]
source = "/assets/**"
headers = { Cache-Control = "no-cache" }

[[advanced.headers]]
source = "/assets/**"
status = [200, 206, 304]
headers = { Cache-Control = "public, max-age=31536000, immutable" }
```