Re: do haproxy has no preempt option
On Wed, Dec 03, 2014 at 03:58:47AM +, jack wrote: > I have four servers one active,and three backup > > when my active server down, > haproxy will switch new traffic to the first backup server > > my question is : > > when the active server retore UP state, > the traffic will auto switch to the active server ,this is not my want. > another switch , it is not my want. > I want the old active server switch to backup State, and the backup server > switch > to active. We wanted to implement this mechanism for a long time for database servers, until we realized that it would lead multiple haproxy servers to quickly become out of sync consecutive to short outages that are not detected by all of them. So right now the best way to implement this is to use stick tables (which can be synchronized). Just stick on something which does not change (eg: "true" or "dst") : backend foo stick-table type ip size 1 stick on dst server s1 1.1.1.1: server s2 2.2.2.2: server s3 3.3.3.3: Willy
do haproxy has no preempt option
I have four servers one active,and three backup when my active server down, haproxy will switch new traffic to the first backup server my question is : when the active server retore UP state, the traffic will auto switch to the active server ,this is not my want. another switch , it is not my want. I want the old active server switch to backup State, and the backup server switch to active.
❶ Internet ❷ Television ❸ Telephonie
Si vous ne visualisez pas correctement ce message, veuillez suivre ce lien consultez-la en ligne Numericable - Le Très Haut Débit partout Numericable La puissance de la Fibre Numericable La puissance de la Fibre Numericable j'en profite Numericable LaBox Fibre Internet Très Haut Débit Télévision HD & VOD Services TV Téléphonie fixe illimitée Numericable - Le Très Haut Débit partout Numericable - Le Très Haut Débit partout Numericable - Le Très Haut Débit partout Si vous ne souhaitez plus recvoir d'informations de notre part, Vous pouvez vous désinscrire
Re: [PATCH 1/2] MINOR: checks: allow external checks in backend sections
On Tue, Dec 02, 2014 at 11:41:39PM +0100, Cyril Bonté wrote: > Le 02/12/2014 22:48, Willy Tarreau a écrit : > >On Tue, Dec 02, 2014 at 10:22:40PM +0100, Cyril Bonté wrote: > >>Currently, HAPROXY_SERVER_CURCONN will never change from its initial > >>value. That's embarrassing, maybe I'll have to change several parts of > >>the previous patch in order to manage such variables. > > > >Don't worry, this branch is tagged development for a reason :-) > >There's no reason to feel embarrassed by pushing things which > >don't work, especially when several eyes watched it and didn't > >notice anything! > > > >If you're not sure how to fix it, we can discuss it tomorrow if you want. > > Well, I think I won't reinvent the wheel. I'll reproduce what is done > for check_statuses. > > I'll create an enum to index the environment variables > enum { > /* General use */ > EXTCHECK_PATH = 0, > > /* Proxy specific environment variables */ > EXTCHECK_HAPROXY_PROXY_NAME, > EXTCHECK_HAPROXY_PROXY_ID, > EXTCHECK_HAPROXY_PROXY_ADDR, > EXTCHECK_HAPROXY_PROXY_PORT, > > /* Server specific environment variables */ > EXTCHECK_HAPROXY_SERVER_NAME, > EXTCHECK_HAPROXY_SERVER_ID, > EXTCHECK_HAPROXY_SERVER_ADDR, > EXTCHECK_HAPROXY_SERVER_PORT, > EXTCHECK_HAPROXY_SERVER_MAXCONN, > EXTCHECK_HAPROXY_SERVER_CURCONN, > EXTCHECK_SIZE > }; > > a new type to store the environment variable name and the max length for > its value, with some specific values to indicate that the length will be > determined at init time, or will require enough space to store a long or > any other string representation. > struct extcheck_env { > char *name; > int val_maxlen; > }; > > This will allow to initialize all the environment variables, then update > some of them during each check call. Semms to make sense. > It will also allow me to remove the realloc I introduced. Only with > this, I already feel happier ;-) I agree :-) > I've already made some tests and it looks to work well for every cases I > can identify. Perfect! Thanks, Willy
Raquettes badminton / Squash -60
Version en ligne Ajouter nous à votre carnet d’adresses LA KOURSE AUX BONS PLANS GRAND JEU Inscrivez-vous Jusqu'au 8 Décembre Doublez vos Chances : Likez nous Vente du Mercredi 3 Décembre Raquettes Badminton Jusqu'à -60% à partir de 7,45€Jusqu'à -60%Durée : 48H Raquettes Squash Jusqu'à -60% à partir de 15,96€Jusqu'à -60%Durée : 48H BIENTÔT Ouverture Jeudi 04/12 T-shirts imprimés 19,95€-60%Durée : 48H ENTREPRISE FRANCAISESATISFAIT OU REMBOURSÉPAIEMENT 100% SECUREPAIEMENT PAYPALSUIVEZ-NOUS SUR FACEBOOK Veuillez me retirer de votre liste de diffusion
Multiple HAProxies launched at the same time generate same random numbers in smp_fetch_rand
Hello, I'm using HAProxy's rand function in configs to generate random values for HTTP headers. The problem is that multiple HAProxies on the same server that where launched at the same time (it happens sometimes in my system) are using the same seed value and generate the same sequence of random numbers which causes some bugs for me. Here's a patch for src/sample.c that solved this problem. I also need the numbers to be as unique as it possible, so the following patch works with /dev/urandom, but it might be a minor issue and it might be ignored for performance reasons. @@ -14,6 +14,9 @@ #include #include #include +#include +#include +#include #include @@ -1331,7 +1334,33 @@ smp_fetch_rand(struct proxy *px, struct session *s, void *l7, unsigned int opt, const struct arg *args, struct sample *smp, const char *kw) { - smp->data.uint = random(); +int fd; +struct timeval tv; + +gettimeofday(&tv, 0); + +fd = open("/dev/urandom", O_RDONLY); +if (fd == -1) { +fd = open("/dev/random", O_RDONLY | O_NONBLOCK); +} + +srandom((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec); + +/* Use random() only if /dev/urandom or /dev/random don't present +* or can't be used. +*/ +if (fd >= 0) { +ssize_t x = read(fd, &smp->data.uint, sizeof (unsigned int)); + +if (x <= 0) { +smp->data.uint = random(); +} + +close(fd); +} +else { +smp->data.uint = random(); +} /* reduce if needed. Don't do a modulo, use all bits! */ if (args && args[0].type == ARGT_UINT) -- Best regards, Leonid A. Movsesyan
Re: [PATCH 1/2] MINOR: checks: allow external checks in backend sections
Le 02/12/2014 22:48, Willy Tarreau a écrit : On Tue, Dec 02, 2014 at 10:22:40PM +0100, Cyril Bonté wrote: Currently, HAPROXY_SERVER_CURCONN will never change from its initial value. That's embarrassing, maybe I'll have to change several parts of the previous patch in order to manage such variables. Don't worry, this branch is tagged development for a reason :-) There's no reason to feel embarrassed by pushing things which don't work, especially when several eyes watched it and didn't notice anything! If you're not sure how to fix it, we can discuss it tomorrow if you want. Well, I think I won't reinvent the wheel. I'll reproduce what is done for check_statuses. I'll create an enum to index the environment variables enum { /* General use */ EXTCHECK_PATH = 0, /* Proxy specific environment variables */ EXTCHECK_HAPROXY_PROXY_NAME, EXTCHECK_HAPROXY_PROXY_ID, EXTCHECK_HAPROXY_PROXY_ADDR, EXTCHECK_HAPROXY_PROXY_PORT, /* Server specific environment variables */ EXTCHECK_HAPROXY_SERVER_NAME, EXTCHECK_HAPROXY_SERVER_ID, EXTCHECK_HAPROXY_SERVER_ADDR, EXTCHECK_HAPROXY_SERVER_PORT, EXTCHECK_HAPROXY_SERVER_MAXCONN, EXTCHECK_HAPROXY_SERVER_CURCONN, EXTCHECK_SIZE }; a new type to store the environment variable name and the max length for its value, with some specific values to indicate that the length will be determined at init time, or will require enough space to store a long or any other string representation. struct extcheck_env { char *name; int val_maxlen; }; This will allow to initialize all the environment variables, then update some of them during each check call. It will also allow me to remove the realloc I introduced. Only with this, I already feel happier ;-) I've already made some tests and it looks to work well for every cases I can identify. -- Cyril Bonté
Re: [PATCH 1/2] MINOR: checks: allow external checks in backend sections
On Tue, Dec 02, 2014 at 10:22:40PM +0100, Cyril Bonté wrote: > Le 02/12/2014 21:45, Willy Tarreau a écrit : > >On Tue, Dec 02, 2014 at 09:21:35PM +0100, Cyril Bonté wrote: > >>Previously, external checks required to find at least one listener in > >>order to > >>pass the and arguments to the external > >>script. > >>It prevented from declaring external checks in backend sections and > >>haproxy > >>rejected the configuration. > >[...] > > > >Both applied, thank you Cyril! > > OK...but I have a bad news : I just realized that one environment > variable simply won't work. That's what happens when a development is > left in a sleeping state for several weeks :-( > > Currently, HAPROXY_SERVER_CURCONN will never change from its initial > value. That's embarrassing, maybe I'll have to change several parts of > the previous patch in order to manage such variables. Don't worry, this branch is tagged development for a reason :-) There's no reason to feel embarrassed by pushing things which don't work, especially when several eyes watched it and didn't notice anything! If you're not sure how to fix it, we can discuss it tomorrow if you want. Cheers, Willy
[SPAM] Feche 2014 com chave de ouro e dinheiro no bolso - Curso de =??Q?encaderna=E7=E3o?= Artesanal
Title: Lancamento - DVDs Encadernacao Artesanal com Gabaritos em MDF Brinde! Caso não esteja conseguindo visualizar a mensagem, clique aqui ou acesse - www.arteemdvd.com.br Para não receber mais nossos informativos simplesmente responda está mensagem trocando o ASSUNTO por DESCADASTRO ou, se preferir, clique aqui para solicitar o imediato descadastramento de nosso sistema de newsletter. Ainda, por medida de segurança você também pode criar um regra em cliente de e-mails, eliminando automaticamente qualquer mensagem que seja disparada por comerc...@mp3world.com.br
Re: [PATCH 1/2] MINOR: checks: allow external checks in backend sections
Le 02/12/2014 21:45, Willy Tarreau a écrit : On Tue, Dec 02, 2014 at 09:21:35PM +0100, Cyril Bonté wrote: Previously, external checks required to find at least one listener in order to pass the and arguments to the external script. It prevented from declaring external checks in backend sections and haproxy rejected the configuration. [...] Both applied, thank you Cyril! OK...but I have a bad news : I just realized that one environment variable simply won't work. That's what happens when a development is left in a sleeping state for several weeks :-( Currently, HAPROXY_SERVER_CURCONN will never change from its initial value. That's embarrassing, maybe I'll have to change several parts of the previous patch in order to manage such variables. -- Cyril Bonté
Re: [PATCH 1/2] MINOR: checks: allow external checks in backend sections
On Tue, Dec 02, 2014 at 09:21:35PM +0100, Cyril Bonté wrote: > Previously, external checks required to find at least one listener in order to > pass the and arguments to the external script. > It prevented from declaring external checks in backend sections and haproxy > rejected the configuration. [...] Both applied, thank you Cyril! Willy
[PATCH 2/2] MEDIUM: checks: provide environment variables to the external checks
The external command accepted 4 arguments, some with the value "NOT_USED" when not applicable. In order to make the exernal command more generic, this patch also provides the values in environment variables. This allows to provide more information. Currently, the supported environment variables are : PATH, as previously provided. HAPROXY_PROXY_NAME, the backend name HAPROXY_PROXY_ID, the backend id HAPROXY_PROXY_ADDR, the first bind address if available (or empty) HAPROXY_PROXY_PORT, the first bind port if available (or empty) HAPROXY_SERVER_NAME, the server name HAPROXY_SERVER_ID, the server id HAPROXY_SERVER_ADDR, the server address HAPROXY_SERVER_PORT, the server port if available (or empty) HAPROXY_SERVER_MAXCONN, the server max connections HAPROXY_SERVER_CURCONN, the current number of connections on the server --- src/checks.c | 98 +--- 1 file changed, 74 insertions(+), 24 deletions(-) diff --git a/src/checks.c b/src/checks.c index bb8b719..03ddb26 100644 --- a/src/checks.c +++ b/src/checks.c @@ -1568,6 +1568,52 @@ static int init_pid_list(void) { return 0; } +#define EXTCHECK_ARG_MAX 5 +#define EXTCHECK_ENV_ROOM 16 + +#define EXTCHECK_ADD_ENV(check, envname, value, idx) { if (external_check_add_env(check, envname, value, idx)) goto err; } + +/* + * helper function to allocate enough space for new environment variables used + * by external checks. + */ +static int external_check_add_env(struct check *check, const char *envname, const char *value, int *idx) +{ + int len, ret; + + if (*idx % EXTCHECK_ENV_ROOM == 0) { + /* Allocate enough space to store new environment variables */ + char **tmp = realloc(check->envp, (EXTCHECK_ENV_ROOM * ((*idx / EXTCHECK_ENV_ROOM) + 1) + 1) * sizeof(check->envp)); + if (tmp == NULL) { + Alert("Failed to allocate memory for new environment variables. Aborting\n"); + return 1; + } else { + check->envp = tmp; + } + } + /* Instead of sending NOT_USED, sending an empty value is preferable */ + if (strcmp(value, "NOT_USED") == 0) { + value = ""; + } + len = strlen(envname) + strlen(value) + 1; + check->envp[*idx] = malloc(len + 1); + check->envp[*idx + 1] = NULL; + if (!check->envp[*idx]) { + Alert("Failed to allocate memory for the environment variable '%s'. Aborting.\n", envname); + return 1; + } + ret = snprintf(check->envp[*idx], len + 1, "%s=%s", envname, value); + if (ret < 0) { + Alert("Failed to store the environment variable '%s'. Reason : %s. Aborting.\n", envname, strerror(errno)); + return 1; + } + else if (ret != len) { + Alert("Environment variable '%s' was truncated. Aborting.\n", envname); + return 1; + } + (*idx)++; + return 0; +} static int prepare_external_check(struct check *check) { @@ -1575,10 +1621,9 @@ static int prepare_external_check(struct check *check) struct proxy *px = s->proxy; struct listener *listener = NULL, *l; int i; - const char *err_fmt = "Starting [%s:%s] check: out of memory.\n"; + int envidx = 0; const char *path = px->check_path ? px->check_path : DEF_CHECK_PATH; - char host[46]; - char serv[6]; + char buf[256]; list_for_each_entry(l, &px->conf.listeners, by_fe) /* Use the first INET, INET6 or UNIX listener */ @@ -1590,18 +1635,9 @@ static int prepare_external_check(struct check *check) } check->curpid = NULL; + check->envp = NULL; - check->envp = calloc(2, sizeof(check->argv)); - if (!check->envp) - goto err; - check->envp[0] = malloc(strlen("PATH=") + strlen(path) + 1); - if (!check->envp[0]) - goto err; - strcpy(check->envp[0], "PATH="); - strcpy(check->envp[0] + strlen(check->envp[0]), path); - check->envp[1] = NULL; - - check->argv = calloc(6, sizeof(check->argv)); + check->argv = calloc(EXTCHECK_ARG_MAX + 1, sizeof(check->argv)); if (!check->argv) goto err; @@ -1613,10 +1649,10 @@ static int prepare_external_check(struct check *check) } else if (listener->addr.ss_family == AF_INET || listener->addr.ss_family == AF_INET6) { - addr_to_str(&listener->addr, host, sizeof(host)); - check->argv[1] = strdup(host); - port_to_str(&listener->addr, serv, sizeof(serv)); - check->argv[2] = strdup(serv); + addr_to_str(&listener->addr, buf, sizeof(buf)); + check->argv[1] = strdup(buf); + port_to_str(&listener->addr, buf, sizeof(buf)); + check->argv[2] = strdup(bu
[PATCH 1/2] MINOR: checks: allow external checks in backend sections
Previously, external checks required to find at least one listener in order to pass the and arguments to the external script. It prevented from declaring external checks in backend sections and haproxy rejected the configuration. The listener is now optional and values "NOT_USED" are passed if no listener is found. For instance, this is the case with a backend section. This is specific to the 1.6 branch. --- doc/configuration.txt | 15 --- src/checks.c | 17 + 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index 9fb0999..aa6baab 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -5338,13 +5338,14 @@ external-check command The arguments passed to the to the command are: - proxy_address proxy_port server_address server_port - - The proxy_address and proxy_port are derived from the first listener - that is either IPv4, IPv6 or a UNIX socket. It is an error for no such - listeners to exist. In the case of a UNIX socket listener the - proxy_address will be the path of the socket and the proxy_port will - be the string "NOT_USED". + + + The and are derived from the first listener + that is either IPv4, IPv6 or a UNIX socket. In the case of a UNIX socket + listener the proxy_address will be the path of the socket and the + will be the string "NOT_USED". In a backend section, it's not + possible to determine a listener, and both and + will have the string value "NOT_USED". If the command executed and exits with a zero status then the check is considered to have passed, otherwise the check is considered to have diff --git a/src/checks.c b/src/checks.c index 5dc95b2..bb8b719 100644 --- a/src/checks.c +++ b/src/checks.c @@ -1589,11 +1589,6 @@ static int prepare_external_check(struct check *check) break; } - if (!listener) { - err_fmt = "Starting [%s:%s] check: no listener.\n"; - goto err; - } - check->curpid = NULL; check->envp = calloc(2, sizeof(check->argv)); @@ -1612,19 +1607,25 @@ static int prepare_external_check(struct check *check) check->argv[0] = px->check_command; - if (listener->addr.ss_family == AF_INET || + if (!listener) { + check->argv[1] = strdup("NOT_USED"); + check->argv[2] = strdup("NOT_USED"); + } + else if (listener->addr.ss_family == AF_INET || listener->addr.ss_family == AF_INET6) { addr_to_str(&listener->addr, host, sizeof(host)); check->argv[1] = strdup(host); port_to_str(&listener->addr, serv, sizeof(serv)); check->argv[2] = strdup(serv); - } else if (listener->addr.ss_family == AF_UNIX) { + } + else if (listener->addr.ss_family == AF_UNIX) { const struct sockaddr_un *un; un = (struct sockaddr_un *)&listener->addr; check->argv[1] = strdup(un->sun_path); check->argv[2] = strdup("NOT_USED"); - } else { + } + else { goto err; } -- 2.1.3
Re: [PATCH 2/2] MEDIUM: checks: provide environment variables to the external checks
Hi Willy, Le 01/12/2014 08:36, Willy Tarreau a écrit : Hi Cyril, I'm fine with applying your series except a minor detail to fix here : On Sun, Nov 30, 2014 at 11:51:09PM +0100, Cyril Bonté wrote: + sprintf(check->envp[*idx], "%s=%s", envname, value); Please use snprintf() with the allocated length and check the result (ie reject <=0 and >len). Some OSes like OpenBSD emit link-time warning when sprintf() is used, and after some time I tend to find they're right. While the initial use case for sprintf() is generally OK, people modify the format later without realizing the impacts so better be safe from the start. Right, I'm preparing a new patch. -- Cyril Bonté
Re: rewritting headers on the fly using CORS
Le 29/11/2014 01:09, Willy Tarreau a écrit : Hi Charles, On Fri, Nov 28, 2014 at 03:09:05PM +0100, Charles Bijon wrote: Hi, I wonder if when using the header rewrite for CORS if - we can simplify keeping the origin in a variable on the fly and of course with a list of acl for accept this domain or - that one is forced to use a different backend to each domain. example: in the backend using : rspadd Access-Control-Allow-Origin: $(hdr(origin)) But I do not know if this concept of variable is possible with haproxy. Today, i am using one backend for each origin domain with different way of "rspadd Access-Control-Allow-Origin: X" that will be not funny to manage. In 1.5 you have a few tricks to achieve this. The simplest one is exactly the same principle as to what Baptiste explained to Pavlos in the other thread. The only variables that haproxy carries right now during a request/response cycle are : - track-sc keys (only 3 of them and mostly usable as booleans) - header captures - logs (which are in fact captures) There's an extra possibility consisting in capturing payload while processing the TCP layer. This payload will take a capture slot exactly like a header. It's sometimes useful to capture non-header information. If you just need to capture a header, you can have this in your frontend : capture request header origin len 50 And thanks to this, you'll be able to pick it from the responses with capture.req.hdr() where is the index of the capture (typically 0 if this is your only capture). In your case I'd suggest : http-response add-header Access-Control-Allow-Origin %[capture.req.hdr(0)] As you can see it's a bit ugly. But it should do the job. As a side effect, unless you redefine your log format, you'll have this origin header logged between curly braces. Regards, Willy Hi Willy, Thanks you for this method, i will try it next update on ours fronts Regards, Charles
Re: Adding HSTS or custom headers on redirect
On 2 December 2014 at 09:17, Samuel Reed wrote: > I'm running the latest 1.5 release. > > Our site runs primarily on the `www` subdomain, but we want to enable HSTS > for > all subdomains (includeSubdomains). Unfortunately, due to the way HSTS > works, > the HSTS header MUST be present on the redirect from https://example.com > to > https://www.example.com. I am using configuration like: > > rspadd Strict-Transport-Security:\ max-age=31536000;\ includeSubDomains > redirect prefix https://www.example.com code 301 if \ > { hdr(host) -i example.com } > > For whatever reason, even when the rspadd line is before the redirect, no > headers are added to the redirect, making this impossible. I've considered > a fake backend with a fake 503 file to get around this - something like: > > HTTP/1.1 301 Moved Permanently > Cache-Control: no-cache > Content-Length: 0 > Strict-Transport-Security: max-age=31536000; includeSubDomains; preload > Location: https://www.example.com/ > Connection: close > > While this will work, it feels really hacky. Is there a better way to add a > header on a redirect? > > Have a look at the thread 'add response header based on presence of request header', your case matches the case I mentioned there. Cheers, Pavlos
offer advertising material
DearSiror=Madam:IamLinZhang.FromGuangzhouPeipeiPromotionalProducts=Co.,Ltd.Nicemeetingyou.GuangzhouPeipeiPromotionalPr=oductsCo.,Ltd.Itislocate in Guangzhouo=fChina.Itisspecialmanufactureallkindof Advertising=productssuch as:gazebocanopy,foldingtent,beachumbrella,giftumbrell=a,custom flag,backpackbanner,promotionalflag,Aframebanner,popbanner=,trade showdisplay,fabricdisplay,Wavelinedisplaystand,pullupstan=d,x sandandsoon. Mostproduc=tsWithcompetitiveprice,goodservice,goodquality!Moredetailpleasevisiteourwebsite:http://www.worldpeipei.com=20GuangzhouPeipeipromotionalProduct=sCo.,Ltd. Tel:+86-20-86376047= Http://www.worldpeipei.com Http://www.facebook.com/worldpeipei E-mail:world=pei...@yeah.net Skype:worldpeipei
Re: Performance implications of using dynamic maps
Thanks a lot Willy. Yes, I tried my luck with sticky tables, but could not find a way to store key value mapping for 1000s of host names. I will move this to testing, thanks for you help as always :) Thanks Sachin On 12/2/14 1:01 PM, "Willy Tarreau" wrote: >Hi Sachin, > >On Sat, Nov 29, 2014 at 04:19:54PM +0530, Sachin Shetty wrote: >> Hi, >> >> In our architecture, we have thousands of host names resolving to a >>single >> haproxy, we dynamically decide a sticky backend based on our own custom >> sharding. To determine the shard info, we let the request flow in to a >> default apache proxy that processes the requests and also responds >>with >> the shard info. To be able to serve the consequent requests directly >> bypassing the apache, we want to store the shard info received in the >>first >> request in a map and use it for subsequent request >> >> 1. Store the shard info from apache >> backend apache_l1 >> mode http >> http-response set-map(/opt/haproxy/current/conf/proxy.map) >> %[res.hdr(X-Request-Host)] %[res.hdr(X-Backend-Id)] >> server apache_l1 :80 >> >> 2. Use the backend directly for subsequent requests: >> acl is_a_v-1 hdr(host),map(/opt/haproxy/current/conf/proxy.map) a_v-1 >> use_backend l2_haproxy if is_a_v-1 >> >> I have tested this config and it works well, but I am not sure about the >> performance. For every request sent to Apache, we will be adding a key, >> value to the map and we will be looking up the key value for every >>requests >> that is coming in to haproxy is that ok considering that this is very >>high >> performance stack? The haproxy servers are pretty powerful and >>dedicated to >> just doing proxy. > >Here you're using string-to-string mapping, it's one of the cheapest one >since there's no conversion of text to patterns. The string lookups are >performed in a few tens of nanoseconds so that does not count. The update >here will require : > - building a new key : log-format + strdup(result) > - building a new value : log-format + strdup(new) > - lookup of the key in the tree > - replacement or insertion of the key in the tree > - free(old_key) > - free(old_value) > >I suspect that below 10-2 req/s you will not notice a significant >difference. Above it can cost a few percent extra CPU usage. > >It's interesting to see that you have basically reimplemented stickiness >using maps :-) > >Regards, >Willy >
Adding HSTS or custom headers on redirect
I'm running the latest 1.5 release. Our site runs primarily on the `www` subdomain, but we want to enable HSTS for all subdomains (includeSubdomains). Unfortunately, due to the way HSTS works, the HSTS header MUST be present on the redirect from https://example.com to https://www.example.com. I am using configuration like: rspadd Strict-Transport-Security:\ max-age=31536000;\ includeSubDomains redirect prefix https://www.example.com code 301 if \ { hdr(host) -i example.com } For whatever reason, even when the rspadd line is before the redirect, no headers are added to the redirect, making this impossible. I've considered a fake backend with a fake 503 file to get around this - something like: HTTP/1.1 301 Moved Permanently Cache-Control: no-cache Content-Length: 0 Strict-Transport-Security: max-age=31536000; includeSubDomains; preload Location: https://www.example.com/ Connection: close While this will work, it feels really hacky. Is there a better way to add a header on a redirect? Thanks Sam