v2中文文档
项目

reverse_proxy

通过可配置的传输、负载平衡、健康检查、请求操作和缓冲选项,将请求代理到一个或多个后端。

Syntax

reverse_proxy [<matcher>] [<upstreams...>] {
	# 后端
	to      <upstreams...>
	dynamic <module> ...

	# 负载平衡
	lb_policy       <name> [<options...>]
	lb_try_duration <duration>
	lb_try_interval <interval>

	# 主动健康检查
	health_uri      <uri>
	health_port     <port>
	health_interval <interval>
	health_timeout  <duration>
	health_status   <status>
	health_body     <regexp>
	health_headers {
		<field> [<values...>]
	}

	# 被动健康检查
	fail_duration     <duration>
	max_fails         <num>
	unhealthy_status  <status>
	unhealthy_latency <duration>
	unhealthy_request_count <num>

	# 流媒体
	flush_interval <duration>
	buffer_requests
	buffer_responses
	max_buffer_size <size>

	# 请求/header操作
	trusted_proxies [private_ranges] <ranges...>
	header_up   [+|-]<field> [<value|regexp> [<replacement>]]
	header_down [+|-]<field> [<value|regexp> [<replacement>]]
	method <method>
	rewrite <to>

	# 传输(round trip)
	transport <name> {
		...
	}

	# 可以选择拦截来自上游的响应
	@name {
		status <code...>
		header <field> [<value>]
	}
	replace_status [<matcher>] <status_code>
	handle_response [<matcher>] {
		<directives...>

		# 只在 handle_response 中可用的特殊指令
		copy_response [<matcher>] [<status>] {
			status <status>
		}
		copy_response_headers [<matcher>] {
			include <fields...>
			exclude <fields...>
		}
	}
}

上游

  • <upstreams...> 是一个要代理的上游(后端)的列表。
  • to 是一个要代理的上游(后端)的列表。
  • dynamic 配置了一个_动态上游模块。这允许为每个请求动态地获得上游列表。参见下面的动态上游,了解标准动态上游模块的描述。动态上游在每次代理循环迭代时被检索(即如果启用了负载平衡重试,每个请求有可能被检索多次),并且将比静态上游更受欢迎。如果发生错误,代理将退回到使用任何静态配置的上游。

上游地址

静态上游地址可以采取传统的Caddy网络地址或只包含scheme和host/port的URL形式。有效的例子。

  • localhost:4000
  • 127.0.0.1:4000
  • http://localhost:4000
  • https://example.com
  • h2c://127.0.0.1
  • example.com
  • unix//var/php.sock

注意:方案不能混合使用,因为它们修改了常见的传输配置(一个启用了TLS的传输不能同时携带HTTPS和纯文本HTTP)。任何明确的传输配置都不会被覆盖,省略方案或使用其他端口将不会假设一个特定的传输。

此外,上游地址不能包含路径或查询字符串,因为这将意味着在代理时同时重写请求,这种行为没有被定义或支持。如果需要,你可以使用rewrite指令。

如果地址不是URL(即没有方案),那么可以使用占位符,但这使得上游_动态静态_,这意味着在健康检查和负载平衡方面,可能有许多不同的后端作为一个单一的静态上游行事。

当通过HTTPS代理时,你可能需要覆盖Host头,使其与TLS SNI值相匹配,该值被服务器用于路由和证书选择。更多细节见下面的HTTPS部分。

动态上游

Caddy的反向代理标准配备了一些动态上游模块。请注意,使用动态上游对负载平衡和健康检查有影响,这取决于具体的策略配置:主动健康检查不对动态上游运行;如果上游列表相对稳定和一致,负载平衡和被动健康检查效果最好(特别是轮流使用)。理想情况下,动态上游模块只返回健康、可用的后端。

SRV

从SRV DNS记录中检索上游。

	dynamic srv [<full_name>] {
		service   <service>
		proto     <proto>
		name      <name>
		refresh   <interval>
		resolvers <ip...>
		dial_timeout        <duration>
		dial_fallback_delay <duration>
	}
  • <full_name> 是要查询的记录的完整域名(即_service._proto.name)。
  • service 是全名的服务部分。
  • proto 是全名中的协议部分。可以是tcpudp
  • name 是名称部分。或者,如果serviceproto是空的,则是要查询的全域名称。
  • refresh是刷新缓存结果的频率。默认:1m
  • resolvers 是DNS解析器的列表,用于覆盖系统解析器。
  • dial_timeout是拨号查询的超时时间。
  • dial_fallback_delay是在生成RFC 6555快速回退连接之前要等待多长时间。默认:300ms
A/AAAA

从A/AAAA DNS记录中检索上游信息。

	dynamic a [<name> <port>] {
		name      <name>
		port      <port>
		refresh   <interval>
		resolvers <ip...>
		dial_timeout        <duration>
		dial_fallback_delay <duration>
	}
  • name是要查询的域名。
  • port是后端使用的端口。
  • refresh是刷新缓存结果的频率。默认:1m
  • resolvers是DNS解析器的列表,用于覆盖系统解析器。
  • dial_timeout是拨号查询的超时时间。
  • dial_fallback_delay是在生成RFC 6555快速回退连接之前要等待多长时间。默认值: 300ms

负载均衡

只要定义了一个以上的上游,就会使用负载平衡。

  • lb_policy 是负载均衡策略的名称,以及任何选项。默认值:random

    对于涉及散列的策略,使用最高随机权重(HRW)算法,以确保具有相同散列键的客户端或请求被映射到相同的上游,即使上游列表改变。

    • random随机选择一个上游

    • random_choose <n>随机选择两个或多个上游,然后选择负载最小的一个(n通常为2)。

    • first根据配置中定义的顺序,选择第一个可用的上游

    • round_robin依次轮询每条上游

    • least_conn选择当前请求数最少的上游;如果有多个主机的请求数最少,那么就随机选择其中一个主机

    • ip_hash将客户的IP映射到一个对应的上游

    • uri_hash将请求的URI(路径和查询)映射到一个对应的上游。

    • header [field]通过散列头的值,将请求头映射到一个对应的上游;如果指定的头字段不存在,将随机选择一个上游。

    • cookie [<name> [<secret>]]在客户端的第一个请求中(当没有cookie时),随机选择一个上游,并在响应中添加一个Set-Cookie'头(如果没有指定,默认cookie名称为lb)。Cookie的值是所选上游的拨号地址,用HMAC-SHA256加密(使用`作为共享私钥,如果不指定则为空字符串)。

      在随后的请求中,如果存在cookie,cookie值将被映射到相同的上游;如果不可用或没有找到,将选择一个新的随机上游,cookie将被添加到响应中。

      如果你希望使用一个特定的上游来进行调试,你可以用密文对上游地址进行散列,并在你的HTTP客户端(浏览器或其他)设置cookie。例如,使用PHP,你可以运行以下程序来计算cookie值,其中10.1.0.10:8080是你的一个上游的地址,secret是你配置的秘密。

      echo hash_hmac('sha256', '10.1.0.10:8080', 'secret');
      // cdd96966817dd14a99f47ee17451464f29998da170814a16b483e4c1ff4c48cf
      

      你可以通过Javascript控制台在浏览器中设置cookie,例如,设置名为lb的cookie。

      document.cookie = "lb=cdd96966817dd14a99f47ee17451464f29998da170814a16b483e4c1ff4c48cf";
      
  • lb_try_duration 是一个持续时间值,它定义了在下一个可用的主机停机时,为每个请求尝试选择可用的后端多长时间。默认情况下,这种重试是禁用的。当负载均衡试图找到一个可用的上游主机时,客户将等待最多这么长时间。一个合理的起点可能是5s,因为HTTP传输的默认拨号超时是3s,所以如果不能到达第一个选定的上游,应该至少有一次重试的机会;这个值可以自由设置和验证,为你的使用场景寻求合适的平衡点。

  • lb_try_interval 是一个持续时间值,定义了从池中选择下一个主机的等待时间。默认是250ms。只有在向上游主机的请求失败时才会被用到。请注意,如果所有的后端都关闭了,且延迟很低的情况下,把这个值设置为0,并且lb_try_duration不为零的话,会导致CPU死锁(spin)。

主动健康检查

主动健康检查是在后台以计时器的方式进行健康检查:

  • health_uri 是主动健康检查的URI路径(和可选查询)。

  • health_port 是用于主动健康检查的端口,如果与上游的端口不同。

  • health_interval 是一个持续时间值,定义了执行主动健康检查的频率。

  • health_timeout 是一个持续时间值,它定义了在将后端标记为停机之前要等待多久的回复。

  • health_status 是一个健康的后端所期望的HTTP状态代码。可以是一个3位数的状态代码,或以xx结尾的状态代码类。例如:200(这是默认的),或2xx

  • health_body 是一个子字符串或正则表达式,用于匹配活动健康检查的响应体。如果后端没有返回一个匹配的主体,它将被标记为停机。

  • health_headers 允许指定在活动健康检查请求中设置的头文件。如果你需要改变Host头,或者你需要向你的后端提供一些认证作为健康检查的一部分,这很有用。

被动健康检查

被动健康检查是在实际代理的请求中进行的。

  • fail_duration 是一个duration值,定义了记住一个失败请求的时间。持续时间> 0可以启用被动健康检查;默认值是0(关闭)。一个合理的起点可能是30s,以平衡错误率和使不健康的上游重新上线时的响应性;但请自由试验,为你的用例找到正确的平衡。

  • max_fails 是在考虑后端宕机之前,在fail_duration内失败请求的最大数量;必须>=1;默认是1

  • unhealthy_status 如果一个请求的响应是这些状态码之一,则算作失败。可以是3位数的状态码或以xx结尾的状态码类别,例如:4045xx

  • unhealthy_latency 是一个持续时间值,如果一个请求需要这么长时间才能得到响应,则算作失败。

  • unhealthy_request_count 是将一个后端标记为停机前允许的同时请求的数量。换句话说,如果一个特定的后端目前正在处理这么多的请求,那么它被认为是 "超载",其他后端将被优先考虑。

    这应该是一个相当大的数字;配置这个意味着代理将有一个unhealthy_request_count × upstreams_count的总同时请求的限制,任何超过这个点的请求将导致一个错误,因为没有上游可用。

事件

当上游从健康状态转变为不健康状态,或者反之,都会触发一个事件。这些事件可以用于触发其他操作,比如发送通知或记录消息。事件如下所示:

  • healthy:在上游从之前的不健康状态标记为健康时触发。
  • unhealthy:在上游从之前的健康状态标记为不健康时触发。

在这两种情况下,host将作为元数据包含在事件中,以标识状态发生变化的上游。例如,可以在使用exec事件处理程序时将其作为占位符与{event.data.host}一起使用。

流媒体

默认情况下,代理会对响应进行部分缓冲,以提高传输效率。

代理还支持WebSocket连接,它会执行HTTP升级请求,然后将连接转换为双向隧道。

默认情况下,当配置重新加载时,WebSocket连接会被强制关闭(会向客户端和上游服务器发送Close控制消息)。每个请求都会持有对配置的引用,因此关闭旧连接是为了控制内存使用。这种关闭行为可以通过stream_timeoutstream_close_delay选项进行自定义设置。

  • flush_interval 是一个持续时间值,用于调整Caddy刷新响应缓冲区到客户端的频率。默认情况下,不进行周期性刷新。负值(通常为-1)表示“低延迟模式”,它完全禁用响应缓冲,会在每次写入客户端后立即刷新。与此同时,即使客户端提前断开连接,也不会取消对后端的请求。如果响应满足以下情况之一,则该选项会被忽略,响应会被立即刷新到客户端:

    • Content-Typetext/event-stream
    • Content-Length未知
    • 在代理的两端使用HTTP/2Content-Length未知,并且Accept-Encoding未设置或为"identity"。
  • request_buffers 会导致代理从请求体中读取最多<size>字节的数据到缓冲区中,然后再将其发送给上游服务器。这非常低效,只有在上游服务器需要立即读取请求体而没有延迟的情况下才应该这样做(这是上游应用程序应该修复的问题)。该选项接受所有由go-humanize支持的大小格式。

  • response_buffers 会导致代理从响应体中读取最多<size>字节的数据到缓冲区中,然后再返回给客户端。基于性能考虑,应尽量避免使用此选项,但如果后端对内存有更严格的限制,这可能会有用。该选项接受所有由go-humanize支持的大小格式。

  • stream_timeout 是一个持续时间值,超过这个时间后,诸如WebSockets之类的流式请求将在超时结束时被强制关闭。这实质上会在连接保持开启时间过长时取消连接。一个合理的起始值可能是24h,以便清除一天前的连接。默认值:无超时。

  • stream_close_delay 是一个持续时间值,它会延迟流式请求(如WebSockets)在配置卸载时被强制关闭;相反,流将保持开启状态,直到延迟完成。换句话说,启用此选项可以防止在重新加载Caddy配置时立即关闭流。启用此选项可能是一个不错的主意,以避免在前一个配置关闭时断掉了连接它们的大量客户端。一个合理的起始值可能是5m,以便在配置重新加载后让用户在5分钟的时间后自然地离开页面。默认值:无延迟。

头信息

代理可以在自己和后端之间操纵头信息

  • header_up 设置、添加(使用+前缀)、删除(使用-前缀)或执行替换(通过使用两个参数,搜索和替换)在请求头的上游到后端。

  • header_down 在来自后端下游的响应头中设置、添加(使用+前缀)、删除(使用-前缀)或执行替换(通过使用两个参数,搜索和替换)。

例如,要设置一个请求头,覆盖任何现有的值。

header_up Some-Header "the value"

添加一个响应头;注意一个头域可以有多个值。

header_down +Some-Header "first value"
header_down +Some-Header "second value"

要删除一个请求头,防止它到达后端。

header_up -Some-Header

要删除所有匹配的请求,使用后缀匹配。

header_up -Some-*

对一个请求头进行正则表达式替换。

header_up Some-Header "^prefix-([A-Za-z0-9]*)$" "replaced-$1-suffix"

使用的正则表达式语言是RE2,包含在Go中。参见 RE2语法参考Go正则表达式语法概述。替换字符串是expanded,允许使用捕获值,例如$1是第一个捕获组。

默认值

默认情况下,Caddy将传入的头信息—包括Host—传给后端,不做任何修改,有三个例外:

对于这些X-Forwarded-*头,默认情况下,Caddy会忽略它们在传入请求中的值,以防止被欺骗。如果Caddy不是客户连接的第一个服务器(例如,当CDN在Caddy前面时),你可以用一个IP范围(CIDRs)列表来配置trusted_proxies,从这些IP范围传入的请求被信任为发送了这些头信息的允许的值。作为一个捷径,private_ranges可以被配置为信任所有私人IP范围。

trusted_proxies private_ranges

此外,当使用http传输时,如果客户端的请求中缺少Accept-Encoding: gzip头,则会设置该头。这种行为可以通过在传输上使用compression off来禁用。

HTTPS

由于(大多数)头信息在被代理时保留其原始值,当代理到HTTPS时,通常需要用配置的上游地址覆盖Host头信息,这样Host头信息与TLS ServerName值相匹配。例如。

reverse_proxy https://example.com {
	header_up Host {upstream_hostport}
}

重写

默认情况下,Caddy用与传入请求相同的HTTP方法和URI执行上游请求,除非在到达reverse_proxy之前,在中间件链中进行了重写。

在代理之前,请求被克隆;这确保了在处理过程中对请求的任何修改不会泄露给其他处理程序。这在代理后需要继续处理的情况下很有用。

除了头处理之外,请求的方法和URI在被发送到上游之前可以被改变。

  • method 改变克隆请求的HTTP方法。如果方法被改为 "GET "或 "HEAD",那么传入请求的主体将不会被这个处理程序发送到上游。如果你想让一个不同的处理程序消费请求正文,这是很有用的。
  • rewrite 改变克隆请求的URI(路径和查询)。这类似于rewrite指令,除了它不会在这个处理程序的范围内持续进行重写。

这些重写对于像 "预检查请求 "这样的模式通常是有用的,即请求被发送到另一个服务器,以帮助决定如何继续处理当前的请求。

例如,该请求可以被发送到一个认证网关,以决定该请求是否来自一个认证用户(例如,该请求有一个会话cookie)并应该继续,或者应该被重定向到一个登录页面。对于这种模式,Caddy提供了一个快捷指令forward_auth来跳过大部分的配置模板。

传输

Caddy的代理传输是可插入的。

  • transport 定义了与后端通信的方式。默认是 "http"。

http传输

transport http {
	read_buffer             <size>
	write_buffer            <size>
	max_response_header     <size>
	dial_timeout            <duration>
	dial_fallback_delay     <duration>
	response_header_timeout <duration>
	expect_continue_timeout <duration>
	resolvers <ip...>
	tls
	tls_client_auth <automate_name> | <cert_file> <key_file>
	tls_insecure_skip_verify
	tls_timeout <duration>
	tls_trusted_ca_certs <pem_files...>
	tls_server_name <server_name>
	tls_renegotiation <level>
	tls_except_ports <ports...>
	keepalive [off|<duration>]
	keepalive_interval <interval>
	keepalive_idle_conns <max_count>
	keepalive_idle_conns_per_host <count>
	versions <versions...>
	compression off
	max_conns_per_host <count>
}
  • read_buffer 是读取缓冲区的大小,单位是字节。它接受go-humanize支持的所有格式。默认值:4KiB

  • write_buffer 是写缓冲区的大小,单位是字节。它接受go-humanize支持的所有格式。默认值:4KiB

  • max_response_header 是从响应头文件中读取的最大字节量。它接受[go-humanize](https://github.com/dustin/go-humanize/blob/master/bytes.go)支持的所有格式。默认值:10MiB

  • dial_timeout 是连接到上游套接字时需要等待的时间。接受持续时间值。默认值。没有超时。

  • dial_fallback_delay 是在生成RFC 6555快速回落连接之前要等待多长时间。负值会使其失效。接受[持续时间值](/docs/conventions#durations)。默认值:300ms

  • response_header_timeout 是从上游读取响应头的等待时间。接受[持续时间值](/docs/conventions#durations)。默认值。没有超时。

  • expect_continue_timeout 是指如果请求有头 "Expect: 100-continue",在完全写入请求头之后,等待上游的第一个响应头的时间。接受[持续时间值](/docs/conventions#durations)。默认值。没有超时。

  • resolvers 是一个DNS解析器的列表,用于覆盖系统解析器。

  • tls 使用HTTPS与后端。如果你使用https://方案或端口:443指定后端,或者配置了以下任何tls_*选项,这将被自动启用。

  • tls_client_auth 启用TLS客户端认证的两种方式之一:(1)通过指定一个域名,Caddy应该为其获得证书并保持更新,或者(2)通过指定一个证书和密钥文件,以便向后端提交TLS客户端认证。

  • tls_insecure_skip_verify 关闭TLS握手验证,使连接不安全,容易受到中间人攻击。请不要在生产中使用。

  • tls_timeout 是一个持续时间值,指定等待TLS握手完成的时间。默认值。没有超时。

  • tls_trusted_ca_certs 是一个PEM文件的列表,指定连接到后端时要信任的CA公钥。

  • tls_server_name 设置验证TLS握手中收到的证书时使用的服务器名称。默认情况下,这将使用上游地址的主机部分。

    只有当你的上游地址与上游可能使用的证书不匹配时,你才需要重写这个。例如,如果上游地址是一个IP地址,那么你需要将其配置为上游服务器所提供的主机名。

    可以使用一个请求占位符,在这种情况下,每次请求都会使用HTTP传输配置的克隆,这可能会产生性能损失。

  • tls_renegotiation 设置TLS重新协商级别。TLS重新协商是在第一次握手后执行后续握手的行为。该级别可以是以下之一。

    • never(默认)禁止重新协商。
    • once允许远程服务器在每个连接中请求重新协商一次。
    • freely允许远程服务器反复请求重新协商。
  • tls_except_ports 当TLS被启用时,如果上游目标使用给定的端口之一,TLS将被禁止用于这些连接。这在配置动态上游时可能很有用,一些上游期待HTTP,另一些期待HTTPS请求。

  • keepalive off或者一个持续时间值,指定保持连接开放的时间(超时)。默认值:2m

  • keepalive_interval 是一个持续时间值,它指定了探测有效性的频率。默认值:`30s'。

  • keepalive_idle_conns 定义了要保持活的最大连接数。默认值。没有限制。

  • keepalive_idle_conns_per_host 如果非零,控制每个主机保持的最大空闲(keep-alive)连接。默认值:32

  • versions 允许自定义支持哪些版本的HTTP。作为一个特例,"h2c "是一个有效的值,它将启用到上游的明文HTTP/2连接(然而,这是一个非标准的功能,不使用Go的默认HTTP传输,所以它是排斥其他功能的;可能会被改变或删除)。默认:1.1 2,如果方案是h2c://,则是h2c 2

  • 压缩 可以通过设置为 "off "来禁止对后端进行压缩。

  • max_conns_per_host 可以选择限制每个主机的总连接数,包括处于拨号、活动和空闲状态的连接。默认值。没有限制。

fastcgi传输

transport fastcgi {
	root  <path>
	split <at>
	env   <key> <value>
	resolve_root_symlink
	dial_timeout  <duration>
	read_timeout  <duration>
	write_timeout <duration>
}
  • root 是网站的根。默认:{http.vars.root}或当前工作目录。

  • split 是分割路径的位置,以便在URI的末端获得PATH_INFO。

  • env 设置一个额外的环境变量为给定值。可以为多个环境变量指定一次以上。

  • resolve_root_symlink 通过评估一个符号链接(如果存在的话),可以将root目录解析为其实际值。

  • dial_timeout 是连接到上游套接字时要等待多长时间。接受[持续时间值](/docs/conventions#durations)。默认值:`3s'。

  • read_timeout 是指从FastCGI服务器读取数据时的等待时间。接受[持续时间值](/docs/conventions#durations)。默认值:没有超时。

  • write_timeout 是向FastCGI服务器发送时要等待多长时间。接受[持续时间值](/docs/conventions#durations)。默认:没有超时。

拦截响应

反向代理可以被配置为拦截来自后端的响应。为了方便,可以定义响应匹配器(类似于请求匹配器的语法),第一个匹配的handle_response路由将被调用。

当一个响应处理程序被调用时,来自后端的响应不会被写入客户端,而配置的handle_response路由将被执行,并由该路由来写入响应。如果路由不写响应,那么请求处理将继续由任何在这个reverse_proxy之后的处理程序进行。

  • @name是一个响应匹配器的名字。只要每个响应匹配器有一个唯一的名字,就可以定义多个匹配器。响应可以根据状态代码和响应头的存在或值进行匹配。
  • replace_status 当被给定匹配器匹配时,简单地改变响应的状态代码。
  • handle_response 定义了在被给定的匹配器(或者,如果省略了匹配器,则是所有响应)匹配时要执行的路由。第一个匹配块将被应用。在handle_response块内,可以使用任何其他[指令](/docs/caddyfile/指令)。

此外,在handle_response里面,可以使用两个特殊的处理指令。

  • copy_response 将从后端收到的响应体复制到客户端。在这样做的时候,可以选择允许改变响应的状态代码。这个指令[在respond之前排序](/docs/caddyfile/directives#directive-order)。
  • copy_response_headers 从后端复制响应头信息到客户端,可以选择包括_或排除一列头信息字段(不能同时指定includeexclude)。这个指令是[在header之后排序](/docs/caddyfile/directives#directive-order)。

在 "handle_response "路由中,有三个占位符可用:

  • {rp.status_code} 来自后端响应的状态代码。
  • {rp.status_text} 来自后端响应的状态文本。
  • {rp.header.*} 来自后端响应的头信息。

响应匹配器

响应匹配器可用于按特定标准过滤(或分类)响应。

status
status <code...>

按HTTP状态代码。

  • <code...> 是一个HTTP状态代码的列表。特殊情况是2xx, 3xx, ...分别与200-299, 300-399, ...范围内的所有状态码相匹配。

参见header请求匹配器的支持语法。

示例

反向代理所有请求到本地后端:

reverse_proxy localhost:9005

在3个后端之间负载平衡所有请求:

reverse_proxy node1:80 node2:80 node3:80

同样的,但只有/api内的请求,并且使用header策略实现负载均衡:

reverse_proxy /api/* node1:80 node2:80 node3:80 {
	lb_policy header X-My-Header
}

配置一些传输选项:

reverse_proxy localhost:8080 {
	transport http {
		dial_timeout 2s
		response_header_timeout 30s
	}
}

反向代理到一个HTTPS端点:

reverse_proxy https://example.com {
	header_up Host {upstream_hostport}
}

在代理前去除一个路径前缀:

handle_path /prefix/* {
	reverse_proxy localhost:9000
}

在代理之前替换一个路径前缀:

handle_path /old-prefix/* {
	rewrite * /new-prefix{path}
	reverse_proxy localhost:9000
}

当Caddy在另一个代理或负载平衡器后面,其IP是123.123.123.123,可能设置X-Forwarded-*头以识别原始客户请求的细节,该下游代理必须被列为可信任的,否则Caddy将忽略这些传入的头:

reverse_proxy localhost:8080 {
	trusted_proxies 123.123.123.123
}

支持X-Accel-Redirect,也就是说,按照上游代理的要求提供静态文件:

reverse_proxy localhost:8080 {
	@accel header X-Accel-Redirect *
	handle_response @accel {
		root    * /path/to/private/files
		rewrite * {rp.header.X-Accel-Redirect}
		file_server
	}
}

为来自上游的错误定制错误页面:

reverse_proxy localhost:8080 {
	@error status 500 503
	handle_response @error {
		root    * /path/to/error/pages
		rewrite * /{rp.status_code}.html
		file_server
	}
}

从A/AAAA记录的DNS查询中动态地获取后端:

reverse_proxy {
	dynamic a example.com 9000
}

从SRV记录的DNS查询中动态地获取后端:

reverse_proxy {
	dynamic srv _api._tcp.example.com
}