Finish documenting Caddy 2.8.0 features (#419)

This commit is contained in:
Francis Lavoie 2024-09-29 05:44:26 -04:00 committed by GitHub
parent 6ac5539ef9
commit af347e9623
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 481 additions and 113 deletions

View file

@ -347,6 +347,7 @@ You can use any [Caddy placeholders](/docs/conventions#placeholders) in the Cadd
| `{remote_port}` | `{http.request.remote.port}` |
| `{remote}` | `{http.request.remote}` |
| `{rp.*}` | `{http.reverse_proxy.*}` |
| `{resp.*}` | `{http.intercept.*}` |
| `{scheme}` | `{http.request.scheme}` |
| `{tls_cipher}` | `{http.request.tls.cipher_suite}` |
| `{tls_client_certificate_der_base64}` | `{http.request.tls.client.certificate_der_base64}` |

View file

@ -55,10 +55,12 @@ Directive | Description
**[handle_path](/docs/caddyfile/directives/handle_path)** | Like handle, but strips path prefix
**[header](/docs/caddyfile/directives/header)** | Sets or removes response headers
**[import](/docs/caddyfile/directives/import)** | Include snippets or files
**[intercept](/docs/caddyfile/directives/intercept)** | Intercept responses written by other handlers
**[invoke](/docs/caddyfile/directives/invoke)** | Invoke a named route
**[log](/docs/caddyfile/directives/log)** | Enables access/request logging
**[log_append](/docs/caddyfile/directives/log_append)** | Append a field to the access log
**[log_skip](/docs/caddyfile/directives/log_skip)** | Skip access logging for matched requests
**[log_name](/docs/caddyfile/directives/log_name)** | Override the logger name(s) to write to
**[map](/docs/caddyfile/directives/map)** | Maps an input value to one or more outputs
**[method](/docs/caddyfile/directives/method)** | Change the HTTP method internally
**[metrics](/docs/caddyfile/directives/metrics)** | Configures the Prometheus metrics exposition endpoint
@ -126,6 +128,7 @@ fs
root
log_append
log_skip
log_name
header
copy_response_headers # only in reverse_proxy's handle_response block
@ -145,6 +148,7 @@ forward_auth
request_header
encode
push
intercept
templates
# special routing & dispatching directives

View file

@ -6,6 +6,12 @@ title: encode (Caddyfile directive)
window.$(function() {
// We'll add links to all the subdirectives if a matching anchor tag is found on the page.
addLinksToSubdirectives();
// Response matchers
window.$('pre.chroma .k:contains("status")')
.html('<a href="/docs/caddyfile/response-matchers#status" style="color: inherit;" title="Response matcher">status</a>')
window.$('pre.chroma .k:contains("header")')
.html('<a href="/docs/caddyfile/response-matchers#header" style="color: inherit;" title="Response matcher">header</a>')
});
</script>
@ -23,9 +29,6 @@ encode [<matcher>] <formats...> {
minimum_length <length>
# response matcher single line syntax
match [header <field> [<value>]] | [status <code...>]
# or response matcher block for multiple conditions
match {
status <code...>
header <field> [<value>]
@ -41,7 +44,7 @@ encode [<matcher>] <formats...> {
- **minimum_length** <span id="minimum_length"/> the minimum number of bytes a response should have to be encoded (default: 512).
- **match** <span id="match"/> is a [response matcher](#response-matcher). Only matching responses are encoded. The default looks like this:
- **match** <span id="match"/> is a [response matcher](/docs/caddyfile/response-matchers). Only matching responses are encoded. The default looks like this:
```caddy-d
match {
@ -82,27 +85,6 @@ encode [<matcher>] <formats...> {
```
## Response matcher
**Response matchers** can be used to filter (or classify) responses by specific criteria.
### status
```caddy-d
status <code...>
```
By HTTP status code.
- **&lt;code...&gt;** is a list of HTTP status codes. Special cases are `2xx`, `3xx`, ... which match against all status codes in the range of 200-299, 300-399, ... respectively
### header
See the [header](/docs/caddyfile/matchers#header) request matcher for the supported syntax.
## Examples
Enable Gzip compression:

View file

@ -24,6 +24,8 @@ Most often, the `file_server` directive is paired with the [`root`](root) direct
When errors occur (e.g. file not found `404`, permission denied `403`), the error routes will be invoked. Use the [`handle_errors`](handle_errors) directive to define error routes, and display custom error pages.
When using `browse`, the default output is produced by the the HTML template. Clients may request the directory listing as either JSON or plaintext, by using the `Accept: application/json` or `Accept: text/plain` headers respectively. The JSON output can be useful for scripting, and the plaintext output can be useful for human terminal usage.
## Syntax

View file

@ -56,13 +56,13 @@ header [<matcher>] [[+|-|?|>]<field> [<value>|<find>] [<replace>]] {
- **&lt;find&gt;** is the substring or regular expression to search for.
- **&lt;replace&gt;** is the replacement value; required if performing a search-and-replace.
- **&lt;replace&gt;** is the replacement value; required if performing a search-and-replace. Use `$1` or `$2` and so on to reference capture groups from the search pattern. If the replacement value is `""`, then the matching text is removed from the value. See the [Go documentation](https://golang.org/pkg/regexp/#Regexp.Expand) for details.
- **defer** will force the header operations to be deferred until the response is being written out to the client. This is automatically enabled if any of the header fields are being deleted with `-`, when setting a default value with `?`, or when having used the `>` prefix.
For multiple header manipulations, you can open a block and specify one manipulation per line in the same way.
When using the `?` prefix to set a default header value, it is automatically separated into its own `header` handler, if it was in a `header` block with multiple header operations. [Under the hood](/docs/modules/http.handlers.headers#response/require), using `?` configures a response matcher which applies to the directive's entire handler, which only applies the header operations (like `defer`), but only if the field is not yet set.
When using the `?` prefix to set a default header value, it is automatically separated into its own `header` handler, if it was in a `header` block with multiple header operations. [Under the hood](/docs/modules/http.handlers.headers#response/require), using `?` configures a [response matcher](/docs/caddyfile/response-matchers) which applies to the directive's entire handler, which only applies the header operations (like `defer`), but only if the field is not yet set.
## Examples

View file

@ -0,0 +1,93 @@
---
title: intercept (Caddyfile directive)
---
<script>
window.$(function() {
// Fix response matchers to render with the right color,
// and link to response matchers section
window.$('pre.chroma .k:contains("@")')
.map(function(k, item) {
let text = item.innerText.replace(/</g,'&lt;').replace(/>/g,'&gt;');
let url = '#' + item.innerText.replace(/_/g, "-");
window.$(item).addClass('nd').removeClass('k')
window.$(item).html(`<a href="#response-matcher" style="color: inherit;" title="Response matcher">${text}</a>`);
});
// Response matchers
window.$('pre.chroma .nd:contains("@name")').first().slice(0, 3)
.wrapAll('<span class="nd">').parent()
.html('<a href="/docs/caddyfile/response-matchers" style="color: inherit;">@name</a>')
window.$('pre.chroma .k:contains("replace_status")').first().next()
.html('<a href="/docs/caddyfile/response-matchers" style="color: inherit;" title="Response matcher">[&lt;matcher&gt;]</a>')
window.$('pre.chroma .k:contains("handle_response")').first().next()
.html('<a href="/docs/caddyfile/response-matchers" style="color: inherit;" title="Response matcher">[&lt;matcher&gt;]</a>')
window.$('pre.chroma .k')
.filter((i, el) => el.innerText === 'status')
.html('<a href="/docs/caddyfile/response-matchers#status" style="color: inherit;">status</a>')
window.$('pre.chroma .k:contains("header")').first()
.html('<a href="/docs/caddyfile/response-matchers#header" style="color: inherit;">header</a>')
// We'll add links to all the subdirectives if a matching anchor tag is found on the page.
addLinksToSubdirectives();
});
</script>
# intercept
A generalized abstraction of the [response interception](reverse_proxy#intercepting-responses) feature from the [`reverse_proxy` directive](reverse_proxy). This may be used with any handler that produces responses, including those from plugins like [FrankenPHP](https://frankenphp.dev/)'s `php_server`.
This directive allows you to [match responses](/docs/caddyfile/response-matchers), and the first matching `handle_response` route or `replace_status` will be invoked. When invoked, the original response body is held back, giving the opportunity to that route to write a different response body, with a new status code or with any necessary response header manipulations. If the route does _not_ write a new response body, then original response body is written instead.
## Syntax
```caddy-d
intercept [<matcher>] {
@name {
status <code...>
header <field> [<value>]
}
replace_status [<matcher>] <code>
handle_response [<matcher>] {
<directives...>
}
}
```
- **@name** is the name of a [response matcher](/docs/caddyfile/response-matchers). As long as each response matcher has a unique name, multiple matchers can be defined. A response can be matched on the status code and presence or value of a response header.
- **replace_status** <span id="replace_status"/> simply changes the status code of response when matched by the given matcher.
- **handle_response** <span id="handle_response"/> defines the route to execute when matched by the given matcher (or, if a matcher is omitted, all responses). The first matching block will be applied. Inside a `handle_response` block, any other [directives](/docs/caddyfile/directives) can be used.
Within `handle_response` routes, the following placeholders are available to pull information from the original response:
- `{resp.status_code}` The status code of the original response.
- `{resp.header.*}` The headers from the original response.
## Examples
When using [FrankenPHP](https://frankenphp.dev/)'s `php_server`, you can use `intercept` to implement `X-Accel-Redirect` support, serving static files as requested by the PHP app:
```caddy
localhost {
root * /srv
intercept {
@accel header X-Accel-Redirect *
handle_response @accel {
root * /path/to/private/files
rewrite {resp.header.X-Accel-Redirect}
method GET
file_server
}
}
php_server
}
```

View file

@ -59,7 +59,7 @@ To add custom fields to the log entries, use the [`log_append` directive](log_ap
- [append](#append)
- [Examples](#examples)
Since Caddy v2.5, by default, headers with potentially sensitive information (`Cookie`, `Set-Cookie`, `Authorization` and `Proxy-Authorization`) will be logged with empty values. This behaviour can be disabled with the [`log_credentials`](/docs/caddyfile/options#log-credentials) global server option.
By default, headers with potentially sensitive information (`Cookie`, `Set-Cookie`, `Authorization` and `Proxy-Authorization`) will be logged as `REDACTED` in access logs. This behaviour can be disabled with the [`log_credentials`](/docs/caddyfile/options#log-credentials) global server option.
## Syntax
@ -67,29 +67,34 @@ Since Caddy v2.5, by default, headers with potentially sensitive information (`C
```caddy-d
log [<logger_name>] {
hostnames <hostnames...>
no_hostname
output <writer_module> ...
format <encoder_module> ...
level <level>
}
```
- **logger_name** is an optional override of the logger name for this site.
- **logger_name** <span id="logger_name"/> is an optional override of the logger name for this site.
By default, a logger name is generated automatically, e.g. `log0`, `log1`, and so on depending on the order of the sites in the Caddyfile. This is only useful if you wish to reliably refer to the output of this logger from another logger defined in global options. See [an example](#multiple-outputs) below.
- **hostnames** is an optional override of the hostnames that this logger applies to.
- **hostnames** <span id="hostnames"/> is an optional override of the hostnames that this logger applies to.
By default, the logger applies to the hostnames of the site block it appears in, i.e. the site addresses. This is useful if you wish to define different loggers per subdomain in a [wildcard site block](/docs/caddyfile/patterns#wildcard-certificates). See [an example](#wildcard-logs) below.
- **output** configures where to write the logs. See [`output` modules](#output-modules) below.
- **no_hostname** <span id="no_hostname"/> prevents the logger from being associated with any of the site block's hostnames. By default, the logger is associated with the [site address](/docs/caddyfile/concepts#addresses) that the `log` directive appears in.
This is useful when you want to log requests to different files based on some condition, such as the request path or method, using the [`log_name` directive](/docs/caddyfile/directives/log_name).
- **output** <span id="output"/> configures where to write the logs. See [`output` modules](#output-modules) below.
Default: `stderr`.
- **format** describes how to encode, or format, the logs. See [`format` modules](#format-modules) below.
- **format** <span id="format"/> describes how to encode, or format, the logs. See [`format` modules](#format-modules) below.
Default: `console` if `stderr` is detected to be a terminal, `json` otherwise.
- **level** is the minimum entry level to log. Default: `INFO`.
- **level** <span id="level"/> is the minimum entry level to log. Default: `INFO`.
Note that access logs currently only emit `INFO` and `ERROR` level logs.
@ -251,8 +256,9 @@ format <encoder_module> {
Default: `seconds`.
May be one of:
- `seconds` Floating-point number of seconds elapsed.
- `nano` Integer number of nanoseconds elapsed.
- `s`, `second` or `seconds` Floating-point number of seconds elapsed.
- `ms`, `milli` or `millis` Floating-point number of milliseconds elapsed.
- `ns`, `nano` or `nanos` Integer number of nanoseconds elapsed.
- `string` Using Go's built-in string format, for example `1m32.05s` or `6.31ms`.
- **level_format** The format for levels.

View file

@ -0,0 +1,49 @@
---
title: log_name (Caddyfile directive)
---
# log_name
Overrides the logger name to use for a request when writing access logs with the [`log` directive](log).
This directive is useful when you want to log requests to different files based on some condition, such as the request path or method.
More than one logger name can be specified, such that the request's log gets pushed to more than one matching logger.
This is often paired with the `log` directive's [`no_hostname`](log#no_hostname) option, which prevents the logger from being associated with any of the site block's hostnames, so that only requests that set `log_name` will push logs to that logger.
## Syntax
```caddy-d
log_name [<matcher>] <names...>
```
## Examples
You may want to log requests to different files, for example you might want to log health checks to a separate file from the main access logs.
Using `no_hostname` in a `log` prevents the logger from being associated with any of the site block's hostnames (i.e. `localhost` here), so that only requests that have `log_name` set to that logger's name will receive logs.
```caddy
localhost {
log {
output file ./caddy.access.log
}
log health_check_log {
output file ./caddy.access.health.log
no_hostname
}
handle /healthz* {
log_name health_check_log
respond "Healthy"
}
handle {
respond "Hello World"
}
}
```

View file

@ -11,13 +11,18 @@ window.$(function() {
let text = item.innerText.replace(/</g,'&lt;').replace(/>/g,'&gt;');
let url = '#' + item.innerText.replace(/_/g, "-");
window.$(item).addClass('nd').removeClass('k')
window.$(item).html(`<a href="#response-matcher" style="color: inherit;" title="Response matcher">${text}</a>`);
window.$(item).html(`<a href="/docs/caddyfile/response-matchers" style="color: inherit;" title="Response matcher">${text}</a>`);
});
// Fix matcher placeholder
window.$('pre.chroma .k:contains("handle_response")').first().nextAll().slice(0, 3)
window.$('pre.chroma .nd:contains("@name")').first()
.html('<a href="/docs/caddyfile/response-matchers" style="color: inherit;" title="Response matcher">@name</a>')
window.$('pre.chroma .k:contains("replace_status")').first().next().slice(0, 3)
.wrapAll('<span class="nd">').parent()
.html('<a href="#response-matcher" style="color: inherit;" title="Response matcher">[&lt;matcher&gt;]</a>')
.html('<a href="/docs/caddyfile/response-matchers" style="color: inherit;" title="Response matcher">[&lt;matcher&gt;]</a>')
window.$('pre.chroma .k:contains("handle_response")').first().next().slice(0, 3)
.wrapAll('<span class="nd">').parent()
.html('<a href="/docs/caddyfile/response-matchers" style="color: inherit;" title="Response matcher">[&lt;matcher&gt;]</a>')
// We'll add links to all the subdirectives if a matching anchor tag is found on the page.
addLinksToSubdirectives();
@ -69,6 +74,8 @@ reverse_proxy [<matcher>] [<upstreams...>] {
health_uri <uri>
health_port <port>
health_interval <interval>
health_passes <num>
health_fails <num>
health_timeout <duration>
health_status <status>
health_body <regexp>
@ -126,14 +133,14 @@ reverse_proxy [<matcher>] [<upstreams...>] {
### Upstreams
## Upstreams
- **&lt;upstreams...&gt;** is a list of upstreams (backends) to which to proxy.
- **to** <span id="to"/> is an alternate way to specify the list of upstreams, one (or more) per line.
- **dynamic** <span id="dynamic"/> configures a _dynamic upstreams_ module. This allows getting the list of upstreams dynamically for every request. See [dynamic upstreams](#dynamic-upstreams) below for a description of standard dynamic upstream modules. Dynamic upstreams are retrieved at every proxy loop iteration (i.e. potentially multiple times per request if load balancing retries are enabled) and will be preferred over static upstreams. If an error occurs, the proxy will fall back to using any statically-configured upstreams.
#### Upstream addresses
### Upstream addresses
Static upstream addresses can take the form of a URL that contains only scheme and host/port, or a conventional [Caddy network address](/docs/conventions#network-addresses). Valid examples:
@ -169,12 +176,12 @@ Upstream addresses **cannot** contain paths or query strings, as that would impl
If the address is not a URL (i.e. does not have a scheme), then [placeholders](/docs/caddyfile/concepts#placeholders) can be used, but this makes the upstream _dynamically static_, meaning that potentially many different backends act as a single, static upstream in terms of health checks and load balancing. We recommend using a [dynamic upstreams](#dynamic-upstreams) module instead, if possible. When using placeholders, a port **must** be included (either by the placeholder replacement, or as a static suffix to the address).
#### Dynamic upstreams
### Dynamic upstreams
Caddy's reverse proxy comes standard with some dynamic upstream modules. Note that using dynamic upstreams has implications for load balancing and health checks, depending on specific policy configuration: active health checks do not run for dynamic upstreams; and load balancing and passive health checks are best served if the list of upstreams is relatively stable and consistent (especially with round-robin). Ideally, dynamic upstream modules only return healthy, usable backends.
##### SRV
#### SRV
Retrieves upstreams from SRV DNS records.
@ -201,7 +208,7 @@ Retrieves upstreams from SRV DNS records.
##### A/AAAA
#### A/AAAA
Retrieves upstreams from A/AAAA DNS records.
@ -226,7 +233,7 @@ Retrieves upstreams from A/AAAA DNS records.
- **versions** is the list of IP versions to resolve for. Default: `ipv4 ipv6` which correspond to both A and AAAA records respectively.
##### Multi
#### Multi
Append the results of multiple dynamic upstream modules. Useful if you want redundant sources of upstreams, for example: a primary cluster of SRVs backed up by a secondary cluster of SRVs.
@ -241,7 +248,7 @@ Append the results of multiple dynamic upstream modules. Useful if you want redu
### Load balancing
## Load balancing
Load balancing is typically used to split traffic between multiple upstreams. By enabling retries, it can also be used with one or more upstreams, to hold requests until a healthy upstream can be selected (e.g. to wait and mitigate errors while rebooting or redeploying an upstream).
@ -313,7 +320,7 @@ This is enabled by default, with the `random` policy. Retries are disabled by de
#### Active health checks
### Active health checks
Active health checks perform health checking in the background on a timer. To enable this, `health_uri` or `health_port` are required.
@ -323,19 +330,23 @@ Active health checks perform health checking in the background on a timer. To en
- **health_interval** <span id="health_interval"/> is a [duration value](/docs/conventions#durations) that defines how often to perform active health checks. Default: `30s`.
- **health_passes** <span id="health_passes"/> is the number of consecutive health checks required before marking the backend as healthy again. Default: `1`.
- **health_fails** <span id="health_fails"/> is the number of consecutive health checks required before marking the backend as unhealthy. Default: `1`.
- **health_timeout** <span id="health_timeout"/> is a [duration value](/docs/conventions#durations) that defines how long to wait for a reply before marking the backend as down. Default: `5s`.
- **health_status** <span id="health_status"/> is the HTTP status code to expect from a healthy backend. Can be a 3-digit status code, or a status code class ending in `xx`. For example: `200` (which is the default), or `2xx`.
- **health_body** <span id="health_body"/> is a substring or regular expression to match on the response body of an active health check. If the backend does not return a matching body, it will be marked as down.
- **health_follow_redirects** <span id="health_follow_redirects"/> will cause the health check to follow redirects provided by upstream. Without this setting, a redirect will cause the check to fail.
- **health_follow_redirects** <span id="health_follow_redirects"/> will cause the health check to follow redirects provided by upstream. By default, a redirect response would cause the health check to count as a fail.
- **health_headers** <span id="health_headers"/> allows specifying headers to set on the active health check requests. This is useful if you need to change the `Host` header, or if you need to provide some authentication to your backend as part of your health checks.
#### Passive health checks
### Passive health checks
Passive health checks happen inline with actual proxied requests. To enable this, `fail_duration` is required.
@ -352,7 +363,7 @@ Passive health checks happen inline with actual proxied requests. To enable this
This should be a reasonably large number; configuring this means that the proxy will have a limit of `unhealthy_request_count × upstreams_count` total simultaneous requests, and any requests after that point will result in an error due to no upstreams being available.
### Events
## Events
When an upstream transitions from being healthy to unhealthy or vice-versa, [an event](/docs/caddyfile/options#event-options) is emitted. These events can be used to trigger other actions, such as sending a notification or logging a message. The events are as follows:
@ -363,7 +374,7 @@ In both cases, the `host` is included as metadata in the event to identify the u
### Streaming
## Streaming
By default, the proxy partially buffers the response for wire efficiency.
@ -390,7 +401,7 @@ By default, WebSocket connections are forcibly closed (with a Close control mess
### Headers
## Headers
The proxy can **manipulate headers** between itself and the backend:
@ -438,7 +449,7 @@ header_up Some-Header "^prefix-([A-Za-z0-9]*)$" "replaced-$1-suffix"
The regular expression language used is RE2, included in Go. See the [RE2 syntax reference](https://github.com/google/re2/wiki/Syntax) and the [Go regexp syntax overview](https://pkg.go.dev/regexp/syntax). The replacement string is [expanded](https://pkg.go.dev/regexp#Regexp.Expand), allowing use of captured values, for example `$1` being the first capture group.
#### Defaults
### Defaults
By default, Caddy passes thru incoming headers&mdash;including `Host`&mdash;to the backend without modifications, with three exceptions:
@ -461,7 +472,7 @@ If you're using Cloudflare in front of Caddy, be aware that you may be vulnerabl
Additionally, when using the [`http` transport](#the-http-transport), the `Accept-Encoding: gzip` header will be set, if it is missing in the request from the client. This allows the upstream to serve compressed content if it can. This behavior can be disabled with [`compression off`](#compression) on the transport.
#### HTTPS
### HTTPS
Since (most) headers retain their original value when being proxied, it is often necessary to override the `Host` header with the configured upstream address when proxying to HTTPS, such that the `Host` header matches the TLS ServerName value:
@ -475,7 +486,7 @@ The `X-Forwarded-Host` header is still passed [by default](#defaults), so the up
### Rewrites
## Rewrites
By default, Caddy performs the upstream request with the same HTTP method and URI as the incoming request, unless a rewrite was performed in the middleware chain before it reaches `reverse_proxy`.
@ -493,14 +504,14 @@ For example, the request could be sent to an authentication gateway to decide wh
### Transports
## Transports
Caddy's proxy **transport** is pluggable:
- **transport** <span id="transport"/> defines how to communicate with the backend. Default is `http`.
#### The `http` transport
### The `http` transport
```caddy-d
transport http {
@ -588,20 +599,26 @@ transport http {
- **keepalive_idle_conns_per_host** <span id="keepalive_idle_conns_per_host"/> if non-zero, controls the maximum idle (keep-alive) connections to keep per-host. Default: `32`.
- **versions** <span id="versions"/> allows customizing which versions of HTTP to support. As a special case, "h2c" is a valid value which will enable cleartext HTTP/2 connections to the upstream (however, this is a non-standard feature that does not use Go's default HTTP transport, so it is exclusive of other features; subject to change or removal). Default: `1.1 2`, or if scheme is `h2c://`, `h2c 2`
- **versions** <span id="versions"/> allows customizing which versions of HTTP to support.
Valid options are: `1.1`, `2`, `h2c`, `3`.
Default: `1.1 2`, or if the [upstream's scheme](#upstream-addresses) is `h2c://`, then the default is `h2c 2`.
`h2c` enables cleartext HTTP/2 connections to the upstream. This is a non-standard feature that does not use Go's default HTTP transport, so it is exclusive of other features.
`3` enables HTTP/3 connections to the upstream. ⚠️ This is an experimental feature and is subject to change.
- **compression** <span id="compression"/> can be used to disable compression to the backend by setting it to `off`.
- **max_conns_per_host** <span id="max_conns_per_host"/> optionally limits the total number of connections per host, including connections in the dialing, active, and idle states. Default: No limit.
- **forward_proxy_url** <span id="forward_proxy_url"/> is a parameter that specifies the URL of a server that the HTTP transport will use to proxy requests to the upstream server. This parameter takes precedence over environment variables like HTTP_PROXY. When a value is provided for this parameter, requests will flow through the reverse proxy in the following order:
a. User Agent -> Reverse Proxy
b. Reverse Proxy -> Forward Proxy (specified by `forward_proxy_url`)
c. Forward Proxy -> Upstream Server
- **forward_proxy_url** <span id="forward_proxy_url"/> specifies the URL of a server that the HTTP transport will use to proxy requests to the upstream server. By default, Caddy respects proxy configured via environment variables as per the [Go stdlib](https://pkg.go.dev/golang.org/x/net/http/httpproxy#FromEnvironment) like `HTTP_PROXY`. When a value is provided for this parameter, requests will flow through the reverse proxy in the following order:
- Client (users) 🡒 `reverse_proxy` 🡒 `forward_proxy_url` 🡒 upstream
#### The `fastcgi` transport
### The `fastcgi` transport
```caddy-d
transport fastcgi {
@ -640,47 +657,33 @@ If you're trying to serve a modern PHP application, you may be looking for the [
### Intercepting responses
## Intercepting responses
The reverse proxy can be configured to intercept responses from the backend. To facilitate this, response matchers can be defined (similar to the syntax for request matchers) and the first matching `handle_response` route will be invoked.
The reverse proxy can be configured to intercept responses from the backend. To facilitate this, [response matchers](/docs/caddyfile/response-matchers) can be defined (similar to the syntax for request matchers) and the first matching `handle_response` route will be invoked.
When a response handler is invoked, the response from the backend is not written to the client, and the configured `handle_response` route will be executed instead, and it is up to that route to write a response. If the route does _not_ write a response, then request handling will continue with any handlers that are [ordered after](/docs/caddyfile/directives#directive-order) this `reverse_proxy`.
- **@name** is the name of a [response matcher](#response-matcher). As long as each response matcher has a unique name, multiple matchers can be defined. A response can be matched on the status code and presence or value of a response header.
- **@name** is the name of a [response matcher](/docs/caddyfile/response-matchers). As long as each response matcher has a unique name, multiple matchers can be defined. A response can be matched on the status code and presence or value of a response header.
- **replace_status** <span id="replace_status"/> simply changes the status code of response when matched by the given matcher.
- **handle_response** <span id="handle_response"/> defines the route to execute when matched by the given matcher (or, if a matcher is omitted, all responses). The first matching block will be applied. Inside a `handle_response` block, any other [directives](/docs/caddyfile/directives) can be used.
Additionally, inside `handle_response`, two special handler directives may be used:
- **copy_response** <span id="copy_response"/> copies the response body received from the backend back to the client. Optionally allows changing the status code of the response while doing so. This directive is [ordered before `respond`](/docs/caddyfile/directives#directive-order).
- **copy_response_headers** <span id="copy_response_headers"/> copies the response headers from the backend to the client, optionally including _OR_ excluding a list of headers fields (cannot specify both `include` and `exclude`). This directive is [ordered after `header`](/docs/caddyfile/directives#directive-order).
Three placeholders will be made available within the `handle_response` routes:
- `{rp.status_code}` The status code from the backend's response.
- `{rp.status_text}` The status text from the backend's response.
- `{rp.header.*}` The headers from the backend's response.
#### Response matcher
**Response matchers** can be used to filter (or classify) responses by specific criteria.
##### status
```caddy-d
status <code...>
```
By HTTP status code.
- **&lt;code...&gt;** is a list of HTTP status codes. Special cases are strings like `2xx` and `3xx`, which match against all status codes in the range of `200`-`299` and `300`-`399`, respectively.
##### header
See the [`header`](/docs/caddyfile/matchers#header) request matcher for the supported syntax.

View file

@ -18,23 +18,56 @@ uri [<matcher>] strip_prefix <target>
uri [<matcher>] strip_suffix <target>
uri [<matcher>] replace <target> <replacement> [<limit>]
uri [<matcher>] path_regexp <target> <replacement>
uri [<matcher>] query [-|+]<param> [<value>]
uri [<matcher>] query {
<param> [<value>] [<replacement>]
...
}
```
- The first (non-matcher) argument specifies the operation:
The first (non-matcher) argument specifies the operation:
- **strip_prefix** strips the prefix from the path.
- **strip_prefix** strips the prefix from the path.
- **strip_suffix** strips the suffix from the path.
- **strip_suffix** strips the suffix from the path.
- **replace** performs a substring replacement across the whole URI.
- **replace** performs a substring replacement across the whole URI.
- **path_regexp** performs a regular expression replacement on the path portion of the URI.
- **&lt;target&gt;** is the prefix, suffix, or search string/regular expression. If a prefix, the leading forward slash may be omitted, since paths always start with a forward slash.
- **&lt;target&gt;** is the prefix, suffix, or search string/regular expression. If a prefix, the leading forward slash may be omitted, since paths always start with a forward slash.
- **&lt;replacement&gt;** is the replacement string. Supports using capture groups with `$name` or `${name}` syntax, or with a number for the index, such as `$1`. See the [Go documentation](https://golang.org/pkg/regexp/#Regexp.Expand) for details. If the replacement value is `""`, then the matching text is removed from the value.
- **&lt;replacement&gt;** is the replacement string (only valid with `replace` and `path_regexp`). Supports using capture groups with `$name` or `${name}` syntax, or with a number for the index, such as `$1`. See the [Go documentation](https://golang.org/pkg/regexp/#Regexp.Expand) for details.
- **&lt;limit&gt;** is an optional limit to the maximum number of replacements.
- **&lt;limit&gt;** is an optional limit to the maximum number of replacements (only valid with `replace`).
- **path_regexp** performs a regular expression replacement on the path portion of the URI.
- **&lt;target&gt;** is the prefix, suffix, or search string/regular expression. If a prefix, the leading forward slash may be omitted, since paths always start with a forward slash.
- **&lt;replacement&gt;** is the replacement string. Supports using capture groups with `$name` or `${name}` syntax, or with a number for the index, such as `$1`. See the [Go documentation](https://golang.org/pkg/regexp/#Regexp.Expand) for details. If the replacement value is `""`, then the matching text is removed from the value.
- **query** performs manipulations on the URI query, with the mode depending on the prefix to the parameter name or the count of arguments. A block can be used to specify multiple operations at once, grouped and performed in this order: rename 🡒 set 🡒 append 🡒 replace 🡒 delete.
- With no prefix, the parameter is set with the given value in the query.
For example, `uri query foo bar` will set the value of the `foo` param to `bar`.
- Prefix with `-` to remove the parameter from the query.
For example, `uri query -foo` will delete the `foo` parameter from the query.
- Prefix with `+` to append a parameter to the query, with the given value. This will _not_ overwrite an existing parameter with the same name (omit the `+` to overwrite).
For example, `uri query +foo bar` will append `foo=bar` to the query.
- A param with `>` as an infix will rename the parameter to the value after the `>`.
For example, `uri query foo>bar` will rename the `foo` parameter to `bar`.
- With three arguments, query value regular expression replacement is performed, where the first arg is the query param name, the second is the search value, and the third is the replacement. The first arg (param name) may be `*` to perform the replacement on all query params.
Supports using capture groups with `$name` or `${name}` syntax, or with a number for the index, such as `$1`. See the [Go documentation](https://golang.org/pkg/regexp/#Regexp.Expand) for details. If the replacement value is `""`, then the matching text is removed from the value.
For example, `uri query foo ^(ba)r $1z` would replace the value of the `foo` param, where the value began with `bar` resulting in the value becoming `baz`.
URI mutations occur on the normalized or unescaped form of the URI. However, escape sequences can be used in the prefix or suffix patterns to match only those literal escapes at those positions in the request path. For example, `uri strip_prefix /a/b` will rewrite both `/a/b/c` and `/a%2Fb/c` to `/c`; and `uri strip_prefix /a%2Fb` will rewrite `/a%2Fb/c` to `/c`, but won't match `/a/b/c`.
@ -74,3 +107,44 @@ Collapse all repeated slashes in the request path (but not the request query) to
```caddy-d
uri path_regexp /{2,} /
```
Set the value of the `foo` query parameter to `bar`:
```caddy-d
uri query foo bar
```
Remove the `foo` parameter from the query:
```caddy-d
uri query -foo
```
Rename the `foo` query parameter to `bar`:
```caddy-d
uri query foo>bar
```
Append the `bar` parameter to the query:
```caddy-d
uri query +foo bar
```
Replace the value of the `foo` query parameter where the value begins with `bar` with `baz`:
```caddy-d
uri query foo ^(ba)r $1z
```
Perform multiple query operations at once:
```caddy-d
uri query {
+foo bar
-baz
qux test
renamethis>renamed
}
```

View file

@ -92,13 +92,15 @@ Possible options are (click on each option to jump to its documentation):
}
acme_dns <provider> ...
on_demand_tls {
ask <endpoint>
interval <duration>
burst <n>
ask <endpoint>
permission <module>
interval <duration>
burst <n>
}
key_type ed25519|p256|p384|rsa2048|rsa4096
cert_issuer <name> ...
renew_interval <duration>
cert_lifetime <duration>
ocsp_interval <duration>
ocsp_stapling off
preferred_chains [smallest] {
@ -122,6 +124,7 @@ Possible options are (click on each option to jump to its documentation):
trusted_proxies <module> ...
client_ip_headers <headers...>
metrics
trace
max_header_size <size>
enable_full_duplex
log_credentials
@ -563,7 +566,9 @@ The ask endpoint should return _as fast as possible_, in a few milliseconds, ide
</aside>
- **interval** and **burst** allows `<n>` certificate operations within `<duration>` interval. These are deprecated and will be removed in a future version, due to not working as intended.
- **permission** allows custom modules to be used to determine whether a certificate should be issued for a particular name. The module must implement the [`caddytls.OnDemandPermission` interface](https://pkg.go.dev/github.com/caddyserver/caddy/v2/modules/caddytls#OnDemandPermission). An `http` permission module is included, which is what the `ask` option uses, and remains as a shortcut for backwards compatibility.
- **interval** and **burst** allows `<n>` certificate operations within `<duration>` interval. ⚠️ These are deprecated and will be removed in a future version, due to not working as intended.
```caddy
{
@ -623,6 +628,22 @@ Default: `10m`
```
##### `cert_lifetime`
The validity period to ask the CA to issue a certificate for.
This value is used to compute the `notAfter` field of the ACME order; therefore the system must have a reasonably synchronized clock. NOTE: Not all CAs support this. Check with your CA's ACME documentation to see if this is allowed and what values may be used.
Default: `0` (CA chooses lifetime, usually 90 days)
⚠️ This is an experimental feature. Subject to change or removal.
```caddy
{
cert_lifetime 30d
}
```
##### `ocsp_interval`
How often to check if [OCSP staples <img src="/old/resources/images/external-link.svg" class="external-link">](https://en.wikipedia.org/wiki/OCSP_stapling) need updating.
@ -920,6 +941,23 @@ Enables Prometheus metrics collection; necessary before scraping metrics. Note t
```
##### `trace`
Log each individual handler that is invoked. Requires that the log emit at `DEBUG` level ( You may do so with the [`debug` global option](#debug)).
NOTE: This may log the configuration of your HTTP handler modules; do not enable this in insecure contexts when there is sensitive data in the configuration.
⚠️ This is an experimental feature. Subject to change or removal.
```caddy
{
servers {
trace
}
}
```
##### `max_header_size`
The maximum size to parse from a client's HTTP request headers. If the limit is exceeded, the server will respond with HTTP status `431 Request Header Fields Too Large`. It accepts all formats supported by [go-humanize](https://github.com/dustin/go-humanize/blob/master/bytes.go). By default, the limit is `1MB`.
@ -956,7 +994,7 @@ Test thoroughly with your HTTP clients, as some older clients may not support fu
##### `log_credentials`
Since Caddy v2.5, by default, headers with potentially sensitive information (`Cookie`, `Set-Cookie`, `Authorization` and `Proxy-Authorization`) will be logged with empty values in access logs (see the [`log` directive](/docs/caddyfile/directives/log)).
By default, access logs (enabled with the [`log` directive](/docs/caddyfile/directives/log)) with headers that contain potentially sensitive information (`Cookie`, `Set-Cookie`, `Authorization` and `Proxy-Authorization`) will be logged as `REDACTED`.
If you wish to _not_ have these headers redacted, you may enable the `log_credentials` option.

View file

@ -0,0 +1,108 @@
---
title: Response matchers (Caddyfile)
---
<script>
window.$(function() {
// Response matchers
window.$('pre.chroma .nd:contains("@")')
.map(function(k, item) {
let text = item.innerText.replace(/</g,'&lt;').replace(/>/g,'&gt;');
let url = '#' + item.innerText.replace(/_/g, "-");
window.$(item).addClass('nd').removeClass('k')
window.$(item).html(`<a href="#syntax" style="color: inherit;">${text}</a>`);
});
window.$('pre.chroma .k:contains("status")')
.html('<a href="#status" style="color: inherit;">status</a>');
window.$('pre.chroma .k:contains("header")')
.html('<a href="#header" style="color: inherit;">header</a>');
// We'll add links to all the subdirectives if a matching anchor tag is found on the page.
addLinksToSubdirectives();
});
</script>
# Response Matchers
**Response matchers** can be used to filter (or classify) responses by specific criteria.
These typically only appear as config inside of certain other directives, to make decisions on the response as it's being written out to the client.
- [Syntax](#syntax)
- [Matchers](#matchers)
- [status](#status)
- [header](#header)
## Syntax
```caddy-d
@name {
status <code...>
header <field> [<value>]
}
```
## Matchers
### status
```caddy-d
status <code...>
```
By HTTP status code.
- **&lt;code...&gt;** is a list of HTTP status codes. Special cases are strings like `2xx` and `3xx`, which match against all status codes in the range of `200`-`299` and `300`-`399`, respectively.
#### Example:
```caddy-d
@success status 2xx
```
### header
```caddy-d
header <field> [<value>]
```
By response header fields.
- `<field>` is the name of the HTTP header field to check.
- If prefixed with `!`, the field must not exist to match (omit value arg).
- `<value>` is the value the field must have to match.
- If prefixed with `*`, it performs a fast suffix match (appears at the end).
- If suffixed with `*`, it performs a fast prefix match (appears at the start).
- If enclosed by `*`, it performs a fast substring match (appears anywhere).
- Otherwise, it is a fast exact match.
Different header fields within the same set are AND-ed. Multiple values per field are OR'ed.
Note that header fields may be repeated and have different values. Backend applications MUST consider that header field values are arrays, not singular values, and Caddy does not interpret meaning in such quandaries.
#### Example:
Match responses with the `Foo` header containing the value `bar`:
```caddy-d
@upgrade header Foo *bar*
```
Match responses with the `Foo` header having the value `bar` OR `baz`:
```caddy-d
@foo {
header Foo bar
header Foo baz
}
```
Match responses that do not have the `Foo` header field at all:
```caddy-d
@not_foo header !Foo
```

View file

@ -319,7 +319,7 @@ Because this command uses the API, the admin endpoint must not be disabled.
`--config` is the config file to apply. If `-`, the config is read from stdin. If not specified, it will try a file called `Caddyfile` in the current working directory and, if it exists, it will adapt it using the `caddyfile` config adapter; otherwise, it is an error if there is no config file to load.
`--adapter` specifies a config adapter to use, if any.
`--adapter` specifies a config adapter to use, if any. This flag is not necessary if the `--config` filename starts with `Caddyfile` or ends with `.caddyfile` which assumes the `caddyfile` adapter. Otherwise, this flag is required if the provided config file is not in Caddy's native JSON format.
`--address` needs to be used if the admin endpoint is not listening on the default address and if it is different from the address in the provided config file. Note that only TCP addresses are supported at this time.
@ -455,7 +455,7 @@ Runs Caddy and blocks indefinitely; i.e. "daemon" mode.
`--config` specifies an initial config file to immediately load and use. If `-`, the config is read from stdin. If no config is specified, Caddy will run with a blank configuration and use default settings for the [admin API endpoints](/docs/api), which can be used to feed it new configuration. As a special case, if the current working directory has a file called "Caddyfile" and the `caddyfile` config adapter is plugged in (default), then that file will be loaded and used to configure Caddy, even without any command line flags.
`--adapter` is the name of the config adapter to use when loading the initial config, if any. This flag is not necessary if the `--config` filename starts with "Caddyfile" which assumes the `caddyfile` adapter. Otherwise, this flag is required if the provided config file is not in Caddy's native JSON format. Any warnings will be printed to the log, but beware that any adaptation without errors will immediately be used, even if there are warnings. If you want to review the results of the adaptation first, use the [`caddy adapt`](#caddy-adapt) subcommand.
`--adapter` is the name of the config adapter to use when loading the initial config, if any. This flag is not necessary if the `--config` filename starts with `Caddyfile` or ends with `.caddyfile` which assumes the `caddyfile` adapter. Otherwise, this flag is required if the provided config file is not in Caddy's native JSON format. Any warnings will be printed to the log, but beware that any adaptation without errors will immediately be used, even if there are warnings. If you want to review the results of the adaptation first, use the [`caddy adapt`](#caddy-adapt) subcommand.
`--pidfile` writes the PID to the specified file.
@ -654,7 +654,7 @@ Validates a configuration file, then exits. This command deserializes the config
`--config` is the config file to validate. If `-`, the config is read from stdin. Default is the `Caddyfile` in the current directory, if any.
`--adapter` is the name of the config adapter to use, if the config file is not in Caddy's native JSON format. If the config file starts with `Caddyfile`, the `caddyfile` adapter is used by default.
`--adapter` is the name of the config adapter to use. This flag is not necessary if the `--config` filename starts with `Caddyfile` or ends with `.caddyfile` which assumes the `caddyfile` adapter. Otherwise, this flag is required if the provided config file is not in Caddy's native JSON format.
`--envfile` loads environment variables from the specified file, in `KEY=VALUE` format. Comments starting with `#` are supported; keys may be prefixed with `export`; values may be double-quoted (double-quotes within can be escaped); multi-line values are supported.

View file

@ -88,7 +88,7 @@ Placeholders are a similar idea to variables in other software. For example, [ng
</aside>
Placeholders are bounded on either side by curly braces `{ }` and contain the variable name inside, for example: `{foo.bar}`. Placeholder braces can be escaped, `\{like so\}`. Variable names are typically namespaced with dots to avoid collisions across modules.
Placeholders are bounded on either side by curly braces `{ }` and contain the variable name inside, for example: `{foo.bar}`. The opening placeholder brace can be escaped `\{like-this}` to prevent replacement. Variable names are typically namespaced with dots to avoid collisions across modules.
Which placeholders are available depends on the context. Not all placeholders are available in all parts of the config. For example, [the HTTP app sets placeholders](/docs/json/apps/http/#docs) that are only available in areas of the config related to handling HTTP requests.
@ -96,7 +96,8 @@ The following placeholders are always available:
Placeholder | Description
------------|-------------
`{env.*}` | Environment variable (example: `{env.HOME}`)
`{env.*}` | Environment variable; example: `{env.HOME}`
`{file.*}` | Contents from a file; example: `{file./path/to/secret.txt}`
`{system.hostname}` | The system's local hostname
`{system.slash}` | The system's filepath separator
`{system.os}` | The system's OS

View file

@ -15,7 +15,7 @@ An unmarshaler's job is simply to set up your module's type, e.g. by populating
```go
// UnmarshalCaddyfile implements caddyfile.Unmarshaler. Syntax:
//
// gizmo <name> [<option>]
// gizmo <name> [<option>]
//
func (g *Gizmo) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
d.Next() // consume directive name
@ -57,9 +57,9 @@ To accept more configuration than can fit on a single line, you may wish to allo
for nesting := d.Nesting(); d.NextBlock(nesting); {
switch d.Val() {
case "sub_directive_1":
// ...
// ...
case "sub_directive_2":
// ...
// ...
}
}
```
@ -101,20 +101,25 @@ func parseCaddyfileHandler(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler,
See the [`httpcaddyfile` package godoc](https://pkg.go.dev/github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile?tab=doc) for more information about how to use the `httpcaddyfile.Helper` type.
### Handler order
All directives which return HTTP middleware/handler values need to be evaluated in the correct order. For example, a handler that sets the root directory of the site has to come before a handler that accesses the root directory, so that it will know what the directory path is.
The HTTP Caddyfile [has a hard-coded ordering for the standard directives](/docs/caddyfile/directives#directive-order). This ensures that users do not need to know the implementation details of the most common functions of their web server, and makes it easier for them to write correct configurations. A single, hard-coded list also prevents nondeterminism given the extensible nature of the Caddyfile.
**When you register a new handler directive, it must be added to that list before it can be used (outside of a `route` block).** This is done in configuration using one of two methods:
**When you register a new handler directive, it must be added to that list before it can be used (outside of a `route` block).** This is done using one of three methods:
- The [`order` global option](/docs/caddyfile/options) modifies the standard order for that configuration only. For example: `order mydir before respond` will insert a new directive `mydir` to be evaluated before the `respond` handler. Then the directive can be used normally.
- Or, use the directive in a [`route` block](/docs/caddyfile/directives/route). Because directives in a route block are not reordered, the directives used in a route block do not need to appear in the list.
- (Recommended) The plugin author can call [`httpcaddyfile.RegisterDirectiveOrder`](https://pkg.go.dev/github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile#RegisterDirectiveOrder) in `init()` after registering the directive, to insert the directive into the order relative to another [standard directive](/docs/caddyfile/directives#directive-order). Doing so, users can use the directive directly in their sites without extra setup. For example, to insert your directive `gizmo` to be evaluated after the `header` handler:
Please document for your users where in the list is the right place for your directive to be ordered so that they can use it properly.
```go
httpcaddyfile.RegisterDirectiveOrder("gizmo", httpcaddyfile.After, "header")
```
- Users may add the [`order` global option](/docs/caddyfile/options) to modify the standard order for their Caddyfile. For example: `order gizmo before respond` will insert a new directive `gizmo` to be evaluated before the `respond` handler. Then the directive can be used normally.
- Users can place the directive in a [`route` block](/docs/caddyfile/directives/route). Because directives in a route block are not reordered, the directives used in a route block do not need to appear in the list.
If you choose one of the latter two options, please document a recommendation for your users for where in the list is the right place for your directive to be ordered, so that they can use it properly.
### Classes
@ -129,7 +134,6 @@ tls.connection_policy | `*caddytls.ConnectionPolicy` | TLS connection policy
tls.cert_issuer | `certmagic.Issuer` | TLS certificate issuer
tls.cert_loader | `caddytls.CertificateLoader` | TLS certificate loader
## Server Types
Structurally, the Caddyfile is a simple format, so there can be different types of Caddyfile formats (sometimes called "server types") to suit different needs.