| | | 1 | | <# |
| | | 2 | | .SYNOPSIS |
| | | 3 | | Registers the built-in aggregated health endpoint for the active Kestrun server. |
| | | 4 | | .DESCRIPTION |
| | | 5 | | Wraps the Kestrun host health extension to add (or replace) the HTTP endpoint that aggregates |
| | | 6 | | all registered health probes. Most parameters are optional and override the defaults provided by |
| | | 7 | | the active host configuration. When no overrides are supplied the endpoint is registered at |
| | | 8 | | '/health' and inherits the server's existing security posture. |
| | | 9 | | .PARAMETER Server |
| | | 10 | | The Kestrun host instance to configure. If omitted, the current server context is resolved automatically. |
| | | 11 | | .PARAMETER Pattern |
| | | 12 | | The relative URL pattern for the endpoint (for example '/healthz'). Must begin with '/'. |
| | | 13 | | .PARAMETER DefaultTags |
| | | 14 | | Optional collection of probe tags to evaluate when the incoming request does not specify an explicit tag filter. |
| | | 15 | | .PARAMETER AllowAnonymous |
| | | 16 | | Set to $true to permit anonymous calls or $false to require authentication. When omitted, the existing configuration |
| | | 17 | | .PARAMETER TreatDegradedAsUnhealthy |
| | | 18 | | Set to $true to return HTTP 503 when any probe reports a degraded state. Defaults to $false. |
| | | 19 | | .PARAMETER ThrowOnDuplicate |
| | | 20 | | When $true, throws if another GET route already exists at the specified pattern. Otherwise the endpoint is skipped w |
| | | 21 | | .PARAMETER RequireSchemes |
| | | 22 | | Optional list of authentication schemes required to access the endpoint. |
| | | 23 | | .PARAMETER RequirePolicies |
| | | 24 | | Optional list of authorization policies required to access the endpoint. |
| | | 25 | | .PARAMETER CorsPolicyName |
| | | 26 | | Optional ASP.NET Core CORS policy name applied to the endpoint. |
| | | 27 | | .PARAMETER RateLimitPolicyName |
| | | 28 | | Optional ASP.NET Core rate limiting policy name applied to the endpoint. |
| | | 29 | | .PARAMETER ShortCircuit |
| | | 30 | | Set to $true to short-circuit the pipeline with the health result. |
| | | 31 | | .PARAMETER ShortCircuitStatusCode |
| | | 32 | | Overrides the status code used when ShortCircuit is $true. |
| | | 33 | | .PARAMETER OpenApiSummary |
| | | 34 | | Overrides the OpenAPI summary documented for the endpoint. |
| | | 35 | | .PARAMETER OpenApiDescription |
| | | 36 | | Overrides the OpenAPI description documented for the endpoint. |
| | | 37 | | .PARAMETER OpenApiOperationId |
| | | 38 | | Overrides the OpenAPI operation id documented for the endpoint. |
| | | 39 | | .PARAMETER OpenApiTags |
| | | 40 | | Overrides the OpenAPI tag list documented for the endpoint. |
| | | 41 | | .PARAMETER OpenApiGroupName |
| | | 42 | | Overrides the OpenAPI group name documented for the endpoint. |
| | | 43 | | .PARAMETER MaxDegreeOfParallelism |
| | | 44 | | Limits the number of concurrent probes executed during a health request. |
| | | 45 | | .PARAMETER ProbeTimeout |
| | | 46 | | Adjusts the timeout enforced for each probe during a health request. |
| | | 47 | | .PARAMETER DefaultScriptLanguage |
| | | 48 | | Overrides the default script language used when registering script-based probes. |
| | | 49 | | .PARAMETER ResponseContentType |
| | | 50 | | Controls the response payload format returned by the endpoint (Json, Yaml, Xml, or Auto for content negotiation). |
| | | 51 | | .PARAMETER XmlRootElementName |
| | | 52 | | When emitting XML output, overrides the root element name (defaults to 'Response'). Ignored for non-XML formats. |
| | | 53 | | .PARAMETER Compress |
| | | 54 | | When set, JSON and XML output are compact (no indentation). By default output is human readable. |
| | | 55 | | .PARAMETER PassThru |
| | | 56 | | Emits the configured server instance so the call can be chained. |
| | | 57 | | .EXAMPLE |
| | | 58 | | Add-KrHealthEndpoint -Pattern '/healthz' -TreatDegradedAsUnhealthy $true -ProbeTimeout '00:00:05' |
| | | 59 | | Registers a health endpoint at /healthz that fails when probes report a degraded status and enforces a 5 second prob |
| | | 60 | | .EXAMPLE |
| | | 61 | | Get-KrServer | Add-KrHealthEndpoint -OpenApiTags 'Diagnostics','Monitoring' -PassThru |
| | | 62 | | Adds the health endpoint to the current server, customises OpenAPI metadata, and returns the server for further conf |
| | | 63 | | #> |
| | | 64 | | function Add-KrHealthEndpoint { |
| | | 65 | | [KestrunRuntimeApi('Definition')] |
| | | 66 | | [CmdletBinding()] |
| | | 67 | | [OutputType([Kestrun.Hosting.KestrunHost])] |
| | | 68 | | param( |
| | | 69 | | [Parameter(ValueFromPipeline = $true)] |
| | | 70 | | [Kestrun.Hosting.KestrunHost]$Server, |
| | | 71 | | |
| | | 72 | | [ValidatePattern('^/')] |
| | | 73 | | [string]$Pattern, |
| | | 74 | | |
| | | 75 | | [string[]]$DefaultTags, |
| | | 76 | | |
| | | 77 | | [bool]$AllowAnonymous, |
| | | 78 | | |
| | | 79 | | [bool]$TreatDegradedAsUnhealthy, |
| | | 80 | | |
| | | 81 | | [bool]$ThrowOnDuplicate, |
| | | 82 | | |
| | | 83 | | [string[]]$RequireSchemes, |
| | | 84 | | |
| | | 85 | | [string[]]$RequirePolicies, |
| | | 86 | | |
| | | 87 | | [string]$CorsPolicyName, |
| | | 88 | | |
| | | 89 | | [string]$RateLimitPolicyName, |
| | | 90 | | |
| | | 91 | | [bool]$ShortCircuit, |
| | | 92 | | |
| | | 93 | | [int]$ShortCircuitStatusCode, |
| | | 94 | | |
| | | 95 | | [string]$OpenApiSummary, |
| | | 96 | | |
| | | 97 | | [string]$OpenApiDescription, |
| | | 98 | | |
| | | 99 | | [string]$OpenApiOperationId, |
| | | 100 | | |
| | | 101 | | [string[]]$OpenApiTags, |
| | | 102 | | |
| | | 103 | | [string]$OpenApiGroupName, |
| | | 104 | | |
| | | 105 | | [ValidateRange(1, [int]::MaxValue)] |
| | | 106 | | [int]$MaxDegreeOfParallelism, |
| | | 107 | | |
| | | 108 | | [timespan]$ProbeTimeout, |
| | | 109 | | |
| | | 110 | | [Kestrun.Scripting.ScriptLanguage]$DefaultScriptLanguage, |
| | | 111 | | |
| | | 112 | | [Kestrun.Health.HealthEndpointContentType]$ResponseContentType, |
| | | 113 | | |
| | | 114 | | [string]$XmlRootElementName, |
| | | 115 | | |
| | | 116 | | [switch]$Compress, |
| | | 117 | | |
| | | 118 | | [switch]$PassThru |
| | | 119 | | ) |
| | | 120 | | begin { |
| | 0 | 121 | | $Server = Resolve-KestrunServer -Server $Server |
| | | 122 | | } |
| | | 123 | | process { |
| | 0 | 124 | | $options = $Server.Options.Health |
| | 0 | 125 | | if ($null -ne $options) { |
| | 0 | 126 | | $options = $options.Clone() |
| | | 127 | | } else { |
| | 0 | 128 | | $options = [Kestrun.Health.HealthEndpointOptions]::new() |
| | | 129 | | } |
| | | 130 | | |
| | 0 | 131 | | if ($PSBoundParameters.ContainsKey('Pattern')) { |
| | 0 | 132 | | $options.Pattern = $Pattern |
| | | 133 | | } |
| | | 134 | | |
| | 0 | 135 | | if ($PSBoundParameters.ContainsKey('DefaultTags')) { |
| | 0 | 136 | | $options.DefaultTags = @($DefaultTags | Where-Object { -not [string]::IsNullOrWhiteSpace($_) }) |
| | | 137 | | } |
| | | 138 | | |
| | 0 | 139 | | if ($PSBoundParameters.ContainsKey('AllowAnonymous')) { |
| | 0 | 140 | | $options.AllowAnonymous = $AllowAnonymous |
| | | 141 | | } |
| | | 142 | | |
| | 0 | 143 | | if ($PSBoundParameters.ContainsKey('TreatDegradedAsUnhealthy')) { |
| | 0 | 144 | | $options.TreatDegradedAsUnhealthy = $TreatDegradedAsUnhealthy |
| | | 145 | | } |
| | | 146 | | |
| | 0 | 147 | | if ($PSBoundParameters.ContainsKey('ThrowOnDuplicate')) { |
| | 0 | 148 | | $options.ThrowOnDuplicate = $ThrowOnDuplicate |
| | | 149 | | } |
| | | 150 | | |
| | 0 | 151 | | if ($PSBoundParameters.ContainsKey('RequireSchemes')) { |
| | 0 | 152 | | $options.RequireSchemes = @($RequireSchemes) |
| | | 153 | | } |
| | | 154 | | |
| | 0 | 155 | | if ($PSBoundParameters.ContainsKey('RequirePolicies')) { |
| | 0 | 156 | | $options.RequirePolicies = @($RequirePolicies) |
| | | 157 | | } |
| | | 158 | | |
| | 0 | 159 | | if ($PSBoundParameters.ContainsKey('CorsPolicyName')) { |
| | 0 | 160 | | $options.CorsPolicyName = $CorsPolicyName |
| | | 161 | | } |
| | | 162 | | |
| | 0 | 163 | | if ($PSBoundParameters.ContainsKey('RateLimitPolicyName')) { |
| | 0 | 164 | | $options.RateLimitPolicyName = $RateLimitPolicyName |
| | | 165 | | } |
| | | 166 | | |
| | 0 | 167 | | if ($PSBoundParameters.ContainsKey('ShortCircuit')) { |
| | 0 | 168 | | $options.ShortCircuit = $ShortCircuit |
| | | 169 | | } |
| | | 170 | | |
| | 0 | 171 | | if ($PSBoundParameters.ContainsKey('ShortCircuitStatusCode')) { |
| | 0 | 172 | | $options.ShortCircuitStatusCode = $ShortCircuitStatusCode |
| | | 173 | | } |
| | | 174 | | |
| | 0 | 175 | | if ($PSBoundParameters.ContainsKey('OpenApiSummary')) { |
| | 0 | 176 | | $options.OpenApiSummary = $OpenApiSummary |
| | | 177 | | } |
| | | 178 | | |
| | 0 | 179 | | if ($PSBoundParameters.ContainsKey('OpenApiDescription')) { |
| | 0 | 180 | | $options.OpenApiDescription = $OpenApiDescription |
| | | 181 | | } |
| | | 182 | | |
| | 0 | 183 | | if ($PSBoundParameters.ContainsKey('OpenApiOperationId')) { |
| | 0 | 184 | | $options.OpenApiOperationId = $OpenApiOperationId |
| | | 185 | | } |
| | | 186 | | |
| | 0 | 187 | | if ($PSBoundParameters.ContainsKey('OpenApiTags')) { |
| | 0 | 188 | | $options.OpenApiTags = @($OpenApiTags) |
| | | 189 | | } |
| | | 190 | | |
| | 0 | 191 | | if ($PSBoundParameters.ContainsKey('OpenApiGroupName')) { |
| | 0 | 192 | | $options.OpenApiGroupName = $OpenApiGroupName |
| | | 193 | | } |
| | | 194 | | |
| | 0 | 195 | | if ($PSBoundParameters.ContainsKey('MaxDegreeOfParallelism')) { |
| | 0 | 196 | | $options.MaxDegreeOfParallelism = $MaxDegreeOfParallelism |
| | | 197 | | } |
| | | 198 | | |
| | 0 | 199 | | if ($PSBoundParameters.ContainsKey('ProbeTimeout')) { |
| | 0 | 200 | | if ($ProbeTimeout -le [timespan]::Zero) { |
| | 0 | 201 | | throw 'ProbeTimeout must be greater than zero.' |
| | | 202 | | } |
| | 0 | 203 | | $options.ProbeTimeout = $ProbeTimeout |
| | | 204 | | } |
| | | 205 | | |
| | 0 | 206 | | if ($PSBoundParameters.ContainsKey('DefaultScriptLanguage')) { |
| | 0 | 207 | | $options.DefaultScriptLanguage = $DefaultScriptLanguage |
| | | 208 | | } |
| | | 209 | | |
| | 0 | 210 | | if ($PSBoundParameters.ContainsKey('ResponseContentType')) { |
| | 0 | 211 | | $options.ResponseContentType = $ResponseContentType |
| | | 212 | | } |
| | | 213 | | |
| | 0 | 214 | | if ($PSBoundParameters.ContainsKey('XmlRootElementName')) { |
| | 0 | 215 | | $options.XmlRootElementName = $XmlRootElementName |
| | | 216 | | } |
| | | 217 | | |
| | 0 | 218 | | if ($PSBoundParameters.ContainsKey('Compress')) { |
| | 0 | 219 | | $options.Compress = $Compress.IsPresent |
| | | 220 | | } |
| | | 221 | | |
| | 0 | 222 | | $result = [Kestrun.Hosting.KestrunHostHealthExtensions]::AddHealthEndpoint($Server, $options) |
| | | 223 | | |
| | 0 | 224 | | if ($PassThru.IsPresent) { |
| | 0 | 225 | | return $result |
| | | 226 | | } |
| | | 227 | | } |
| | | 228 | | } |