www/caddy: Add active health checks (#4721)

* www/caddy: Add active health checks

* www/caddy: Update Caddy model validation rules for health checks

Adjusted regex masks for `health_uri`, `health_upstream`, and `health_status` fields to improve validation accuracy. Changed `health_upstream` to `IPPortField` for better type handling.

* www/caddy: Moved Active checks after Passive checks in UI.
Use defaults for health_upstream IPPortField

* www/caddy: fix default for `health_follow_redirects`
This commit is contained in:
Zach Bensley
2025-05-23 21:42:38 +08:00
committed by GitHub
parent d64bc86a95
commit bc2bb3d982
3 changed files with 169 additions and 0 deletions
@@ -340,4 +340,111 @@
<visible>false</visible>
</grid_view>
</field>
<field>
<id>handle.health_uri</id>
<label>Active Health URI</label>
<type>text</type>
<style>style_reverse_proxy</style>
<help><![CDATA[health_uri is the URI path (and optional query) for active health checks.]]></help>
<grid_view>
<visible>false</visible>
</grid_view>
</field>
<field>
<id>handle.health_upstream</id>
<label>Active Health Upstream</label>
<type>text</type>
<style>style_reverse_proxy</style>
<help><![CDATA[health_upstream is the ip:port to use for active health checks, if different from the upstream. This should be used in tandem with health_header and {http.reverse_proxy.active.target_upstream}]]></help>
<grid_view>
<visible>false</visible>
</grid_view>
</field>
<field>
<id>handle.health_port</id>
<label>Active Health Port</label>
<type>text</type>
<style>style_reverse_proxy</style>
<help><![CDATA[health_port is the port to use for active health checks, if different from the upstream's port. Ignored if health_upstream is used.]]></help>
<grid_view>
<visible>false</visible>
</grid_view>
</field>
<field>
<id>handle.health_interval</id>
<label>Active Health Interval</label>
<type>text</type>
<style>style_reverse_proxy</style>
<hint>30</hint>
<help><![CDATA[health_interval is a duration value that defines how often to perform active health checks. Default: 30s.]]></help>
<grid_view>
<visible>false</visible>
</grid_view>
</field>
<field>
<id>handle.health_passes</id>
<label>Active Health Passes</label>
<type>text</type>
<style>style_reverse_proxy</style>
<hint>1</hint>
<help><![CDATA[health_passes is the number of consecutive health checks required before marking the backend as healthy again. Default: 1.]]></help>
<grid_view>
<visible>false</visible>
</grid_view>
</field>
<field>
<id>handle.health_fails</id>
<label>Active Health Fails</label>
<type>text</type>
<style>style_reverse_proxy</style>
<hint>1</hint>
<help><![CDATA[health_fails is the number of consecutive health checks required before marking the backend as unhealthy. Default: 1.]]></help>
<grid_view>
<visible>false</visible>
</grid_view>
</field>
<field>
<id>handle.health_timeout</id>
<label>Active Health Timeout</label>
<type>text</type>
<style>style_reverse_proxy</style>
<hint>5</hint>
<help><![CDATA[health_timeout is a duration value that defines how long to wait for a reply before marking the backend as down. Default: 5s.]]></help>
<grid_view>
<visible>false</visible>
</grid_view>
</field>
<field>
<id>handle.health_status</id>
<label>Active Health Status</label>
<type>text</type>
<style>style_reverse_proxy</style>
<hint>200</hint>
<help><![CDATA[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.]]></help>
<grid_view>
<visible>false</visible>
</grid_view>
</field>
<field>
<id>handle.health_body</id>
<label>Active Health Body</label>
<type>text</type>
<style>style_reverse_proxy</style>
<help><![CDATA[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.]]></help>
<grid_view>
<visible>false</visible>
</grid_view>
</field>
<field>
<id>handle.health_follow_redirects</id>
<label>Active Health Follow Redirects</label>
<type>checkbox</type>
<style>style_reverse_proxy</style>
<help><![CDATA[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.]]></help>
<grid_view>
<visible>false</visible>
<type>boolean</type>
<formatter>boolean</formatter>
</grid_view>
</field>
</form>
@@ -457,6 +457,38 @@
<ValidationMessage>Please enter a minimum value of 1 or leave empty for defaults.</ValidationMessage>
</PassiveHealthUnhealthyRequestCount>
<description type="DescriptionField"/>
<health_uri type="TextField">
<mask>/^(\/.*)?$/u</mask>
<ValidationMessage>Please enter a valid 'URI' that starts with '/'.</ValidationMessage>
</health_uri>
<health_upstream type="IPPortField"/>
<health_port type="IntegerField">
<MinimumValue>1</MinimumValue>
<MaximumValue>65535</MaximumValue>
<ValidationMessage>Please enter a minimum value of 1-65535 or leave empty for defaults.</ValidationMessage>
</health_port>
<health_interval type="IntegerField">
<MinimumValue>1</MinimumValue>
<ValidationMessage>Please enter a minimum value of 1 or leave empty for defaults.</ValidationMessage>
</health_interval>
<health_passes type="IntegerField">
<MinimumValue>1</MinimumValue>
<ValidationMessage>Please enter a minimum value of 1 or leave empty for defaults.</ValidationMessage>
</health_passes>
<health_fails type="IntegerField">
<MinimumValue>1</MinimumValue>
<ValidationMessage>Please enter a minimum value of 1 or leave empty for defaults.</ValidationMessage>
</health_fails>
<health_timeout type="IntegerField">
<MinimumValue>1</MinimumValue>
<ValidationMessage>Please enter a minimum value of 1 or leave empty for defaults.</ValidationMessage>
</health_timeout>
<health_status type="TextField">
<mask>/^(100|[1-5][0-9]{2}|[1-5]xx)$/u</mask>
<ValidationMessage>Please enter a 3-digit status code or a status code ending in xx or leave empty for defaults.</ValidationMessage>
</health_status>
<health_body type="TextField"/>
<health_follow_redirects type="BooleanField"/>
</handle>
<accesslist type="ArrayField">
<accesslistName type="DescriptionField">
@@ -415,6 +415,36 @@ http://{{ domain }} {
{% if handle.lb_try_interval|default("") %}
lb_try_interval {{ handle.lb_try_interval }}ms
{% endif %}
{% if handle.health_uri|default("") %}
health_uri {{ handle.health_uri }}
{% endif %}
{% if handle.health_upstream|default("") %}
health_uri {{ handle.health_upstream }}
{% endif %}
{% if handle.health_port|default("") %}
health_uri {{ handle.health_port }}
{% endif %}
{% if handle.health_interval|default("") %}
health_uri {{ handle.health_interval }}s
{% endif %}
{% if handle.health_passes|default("") %}
health_uri {{ handle.health_passes }}
{% endif %}
{% if handle.health_fails|default("") %}
health_uri {{ handle.health_fails }}
{% endif %}
{% if handle.health_timeout|default("") %}
health_uri {{ handle.health_timeout }}s
{% endif %}
{% if handle.health_status|default("") %}
health_uri {{ handle.health_status }}
{% endif %}
{% if handle.health_body|default("") %}
health_uri {{ handle.health_body }}
{% endif %}
{% if handle.health_follow_redirects|default("0") == "1" %}
health_follow_redirects
{% endif %}
{% if handle.PassiveHealthFailDuration|default("") %}
fail_duration {{ handle.PassiveHealthFailDuration }}s
{% endif %}