]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add docs for finally
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Tue, 6 May 2025 19:07:16 +0000 (13:07 -0600)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Tue, 6 May 2025 19:07:16 +0000 (13:07 -0600)
doc/antora/modules/reference/nav.adoc
doc/antora/modules/reference/pages/unlang/finally.adoc [new file with mode: 0644]

index ead1e51d09f0848c7c7a0cee11a1f42860714d68..e5ff8a08faa2125dcc9b8ceaafc2ac91bdaf331d 100644 (file)
@@ -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 (file)
index 0000000..ccda852
--- /dev/null
@@ -0,0 +1,131 @@
+= The finally section
+
+.Syntax
+[source,unlang]
+----
+finally [<request-type>] {
+    [ 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 `<request-type>` 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.