From: Arran Cudbard-Bell Date: Tue, 6 May 2025 19:07:16 +0000 (-0600) Subject: Add docs for finally X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5181c90e59d18e29bc2f827fd97c0c06a6c3e48d;p=thirdparty%2Ffreeradius-server.git Add docs for finally --- diff --git a/doc/antora/modules/reference/nav.adoc b/doc/antora/modules/reference/nav.adoc index ead1e51d09f..e5ff8a08faa 100644 --- a/doc/antora/modules/reference/nav.adoc +++ b/doc/antora/modules/reference/nav.adoc @@ -18,6 +18,7 @@ **** xref:unlang/elsif.adoc[elsif] **** xref:unlang/expression.adoc[expressions] **** xref:unlang/filter.adoc[filter] +**** xref:unlang/finally.adoc[finally] **** xref:unlang/foreach.adoc[foreach] **** xref:unlang/group.adoc[group] **** xref:unlang/if.adoc[if] diff --git a/doc/antora/modules/reference/pages/unlang/finally.adoc b/doc/antora/modules/reference/pages/unlang/finally.adoc new file mode 100644 index 00000000000..ccda852cba7 --- /dev/null +++ b/doc/antora/modules/reference/pages/unlang/finally.adoc @@ -0,0 +1,131 @@ += The finally section + +.Syntax +[source,unlang] +---- +finally [] { + [ statements ] +} +---- + +.Description +The intent of the `finally { ... }` section is to allow any logging or cleanup +to be peformed before the request exits the virtual server. For example, +if you wish to log all requests and responses that enter a virtual server, +you could place a single call to `linelog` in the finally section. + +The `finally { ... }` section is executed last before a request exits a +virtual server. It is executed regardless of whether the request was +accepted, rejected or timed out. + +The `` qualifier can be any valid request type for the protocol the +virtual server implments. If a no request-type-specific finally section +is provided, the unqualified `finally { ... }` section is executed. + +.Example of using unqalified finally +[source,unlang] +---- +# Executes first +recv Access-Request { + ... +} + +# Executes second +send Access-Accept { + ... +} + +# Executes third +finally { + linelog.log("Sending %{reply.Packet-Type} to %{NAS-IP-Address}") +} +---- + +.Example of using qualified finally +[source,unlang] +---- +# Executes first +recv Access-Request { + ... +} + +# Executes second +send Access-Accept { + ... +} + +# Executes third +finally Access-Request { + linelog.log("Sending %{reply.Packet-Type} in response to Access-Request to %{NAS-IP-Address}") +} + +# Ignored for Access-Requests, would be called for Accounting-Requests +finally { + ... +} +---- + +== Rcodes +=== Available to finally +The rcode returned by the section executed immediately prior to finally is +preserved, and can be checked within the finally section using +xref:unlang/condition/return_codes.adoc[return code expressions]. +This allows different behaviour based on the result of the protocol state +machine. + +.Example of calling different modules based on the previous rcode +[source,unlang] +---- +# Executes first +recv Access-Request { + ... +} + +send Access-Accept { + ok +} +# returns `ok` + +finally { + if (ok || updated) { + linelog.log("Request succeeded") + } else { + linelog.log("Request failed") + } +} +---- + +=== Returned by finally +The return code of `finally { ... }` sections will not modify the response packet +type from the virtual server. i.e. a `reject` rcode will not result an +`Access-Reject` response being sent for RADIUS. This is because `finally` sections +run _after_ the protocol state machine as completed. + +If, however, a virtual server containing a `finally { ... }` section is called, +the rcode returned by finally will be the rcode returned by the virtual server +and the `call` keyword. + +== Timeouts + +The `finally` section is executed even if the request times out. Requests +terminated by a timeout will have the `timeout` rcode set. This condition +can be checked with `if (timeout)` at the start of the section. + +[NOTE] +==== +Request passing through a `finally { ... }` section will artificially extend +the lifetime of the request until the section completes. To ensure +the server remains responsive, any potentially long running module calls or +xlat expansions should be wrapped in a xref:unlang/timeout.adoc[timeout] block. +==== + +== Subrequests + +Where xref:unlang/subrequest.adoc[subrequest] calls are used, the +`finally { ... }` section in the parent will not be executed until the subrequest +has completed. Timeouts in `finally { ... }` sections in subrequests should be set +appropriately short to ensure that the parent request isn't cancalled due to an +excessively long running subrequest. + +// Copyright (C) 2025 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// This documentation was developed by Network RADIUS SAS.