I've seen a few places online where people are trying to use a substring
in the path / hostname as the stick-key, and I was trying to do the same
today. [1] The current solution appears to be to statically declare
every path / hostname possible, but I was wondering if it was possible
to make it dynamic.
I've attached a patch that allows you to extract a string from another
as a conversion filter. This can be used as follows:
stick on path extract_field(/, 3) # this returns baz from /foo/bar/baz
(the 0th element is an empty string).
Similarly,
stick on hostname extract_field(., 1) would ensure that you correctly
stick a.subdomain.domain.com and b.subdomain.domain.com.
Assumptions in the code (please tell me if these are incorrect):
* Returning 0 from a conversion filter correctly aborts the stick.
* I do not need to garbage collect the sample, after I run smp_dup (I
used 'lower' as the base I started from)
PS: I hope I got the email subject right. Patch also available here:
https://github.com/gja/haproxy.git, just in case this list does not
allow attachments (and I am not sure if people still use git send-email)
[1] http://marc.info/?l=haproxy&m=136212840626459
--
Tejas Dinkar
http://nilenso.com
Nilenso Software LLP
>From 4b40bf6d8b1a345d839a6cd1fab132f84a97cfed Mon Sep 17 00:00:00 2001
From: Tejas Dinkar <te...@gja.in>
Date: Thu, 16 Oct 2014 00:28:40 +0530
Subject: [PATCH] stick: Allows you to extract a field from an input string
This is useful when trying to dynamically choose the stickyness based
on the path, or the hostname.
For example,
stick on path extract_field(/,3)
Will return baz from the path /foo/bar/baz
---
src/sample.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/src/sample.c b/src/sample.c
index 3343739..dc66827 100644
--- a/src/sample.c
+++ b/src/sample.c
@@ -1386,6 +1386,35 @@ static int sample_conv_wt6(const struct arg *arg_p,
struct sample *smp)
return 1;
}
+static int sample_conv_extract_field(const struct arg *args, struct sample
*smp)
+{
+ char *ptr, *separator, *result;
+ unsigned int field_number;
+
+ if (!smp_dup(smp))
+ return 0;
+
+ // This chunk must be correctly terminated for strsep
+ separator = args[0].data.str.str;
+ separator[args[0].data.str.len] = '\0';
+
+ // This chunk must be correctly terminated for strsep
+ ptr = smp->data.str.str;
+ ptr[smp->data.str.len] = '\0';
+
+ for(field_number = args[1].data.uint + 1; field_number > 0;
field_number--) {
+ if(!ptr)
+ return 0;
+ result = strsep(&ptr, separator);
+ }
+
+ smp->data.str.len = strlen(result);
+ if(smp->data.str.str != result)
+ strcpy(smp->data.str.str, result);
+
+ return 1;
+}
+
/************************************************************************/
/* All supported sample fetch functions must be declared here */
/************************************************************************/
@@ -1493,6 +1522,7 @@ static struct sample_conv_kw_list sample_conv_kws = {ILH,
{
{ "djb2", sample_conv_djb2, ARG1(0,UINT), NULL, SMP_T_BIN,
SMP_T_UINT },
{ "sdbm", sample_conv_sdbm, ARG1(0,UINT), NULL, SMP_T_BIN,
SMP_T_UINT },
{ "wt6", sample_conv_wt6, ARG1(0,UINT), NULL, SMP_T_BIN,
SMP_T_UINT },
+ { "extract_field", sample_conv_extract_field, ARG2(2, STR, UINT),
NULL, SMP_T_STR, SMP_T_STR },
{ NULL, NULL, 0, 0, 0 },
}};
--
1.9.3 (Apple Git-50)