From aa5b87964dd4c360e4fdcfbc6e78419032599474 Mon Sep 17 00:00:00 2001
From: Chris Staite <christopher.staite@menlosecurity.com>
Date: Wed, 24 Sep 2025 22:21:43 +0100
Subject: [PATCH 2/2] MINOR: backend: srv_is_up converter

There is currently an srv_queue converter which is capable of taking the
output of a dynamic name and determining the queue length for a given
server.  In addition there is a sample fetcher for whether a server is
currently up.  This simply combines the two such that srv_is_up can be
used as a converter too.

Future work might extend this to other sample fetchers for servers, but
this is probably the most useful for acl routing.
---
 doc/configuration.txt | 11 +++++++++++
 src/backend.c         | 18 ++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/doc/configuration.txt b/doc/configuration.txt
index 62503aefb..1f7694231 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -20144,6 +20144,7 @@ secure_memcmp(var)                                 string       boolean
 set-var(var[,cond...])                              any          same
 sha1                                               binary       binary
 sha2([bits])                                       binary       binary
+srv_is_up                                          string       boolean
 srv_queue                                          string       integer
 strcmp(var)                                        string       boolean
 sub(value)                                         integer      integer
@@ -21405,6 +21406,16 @@ sha2([<bits>])
   Please note that this converter is only available when HAProxy has been
   compiled with USE_OPENSSL.
 
+srv_is_up
+  Takes an input value of type string, either a server name or <backend>/<server>
+  format and returns true when the designated server is currently UP. Can be used
+  in places where we want to look up a server status from a dynamic name, like a
+  cookie value (e.g. req.cook(SRVID),srv_is_up) and then make a decision to
+  direct a request elsewhere. Before using this, please keep in mind that using
+  this converter on uncontrolled data might allow an external observer to query
+  the state of any server in the whole configuration, which might possibly not
+  be acceptable in some environments.
+
 srv_queue
   Takes an input value of type string, either a server name or <backend>/<server>
   format and returns the number of queued streams on that server. Can be used
diff --git a/src/backend.c b/src/backend.c
index 9b5a2fd14..135b2c4a0 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -3763,6 +3763,23 @@ static struct server *sample_conv_srv(struct sample *smp)
 	return server_find(px, smp->data.u.str.area);
 }
 
+static int
+sample_conv_srv_is_up(const struct arg *args, struct sample *smp, void *private)
+{
+	struct server *srv = sample_conv_srv(smp);
+
+	if (!srv)
+		return 0;
+
+	smp->data.type = SMP_T_BOOL;
+	if (!(srv->cur_admin & SRV_ADMF_MAINT) &&
+	    (!(srv->check.state & CHK_ST_CONFIGURED) || (srv->cur_state != SRV_ST_STOPPED)))
+		smp->data.u.sint = 1;
+	else
+		smp->data.u.sint = 0;
+	return 1;
+}
+
 static int
 sample_conv_srv_queue(const struct arg *args, struct sample *smp, void *private)
 {
@@ -3809,6 +3826,7 @@ INITCALL1(STG_REGISTER, sample_register_fetches, &smp_kws);
 /* Note: must not be declared <const> as its list will be overwritten */
 static struct sample_conv_kw_list sample_conv_kws = {ILH, {
 	{ "nbsrv",     sample_conv_nbsrv,     0, NULL, SMP_T_STR, SMP_T_SINT },
+	{ "srv_is_up", sample_conv_srv_is_up, 0, NULL, SMP_T_STR, SMP_T_BOOL },
 	{ "srv_queue", sample_conv_srv_queue, 0, NULL, SMP_T_STR, SMP_T_SINT },
 	{ /* END */ },
 }};
-- 
2.49.0

