From: Willy Tarreau Date: Sat, 23 Oct 2010 10:46:42 +0000 (+0200) Subject: [MINOR] cookie: add support for the "preserve" option X-Git-Tag: v1.5-dev8~427 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ba4c5be88098eb9bf43cb47960dfac2e96623748;p=thirdparty%2Fhaproxy.git [MINOR] cookie: add support for the "preserve" option This option makes haproxy preserve any persistence cookie emitted by the server, which allows the server to change it or to unset it, for instance, after a logout request. (cherry picked from commit 52e6d75374c7900c1fe691c5633b4ae029cae8d5) --- diff --git a/doc/configuration.txt b/doc/configuration.txt index d05ad9ea59..ae4827a88a 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -1675,7 +1675,7 @@ contimeout (deprecated) cookie [ rewrite | insert | prefix ] [ indirect ] [ nocache ] - [ postonly ] [ domain ]* + [ postonly ] [ preserve ] [ domain ]* [ maxidle ] [ maxlife ] Enable cookie-based persistence in a backend. May be used in sections : defaults | frontend | listen | backend @@ -1705,16 +1705,18 @@ cookie [ rewrite | insert | prefix ] [ indirect ] [ nocache ] insert This keyword indicates that the persistence cookie will have to be inserted by haproxy in server responses if the client did not + already have a cookie that would have permitted it to access this - server. If the server emits a cookie with the same name, it will - be remove before processing. For this reason, this mode can be - used to upgrade existing configurations running in the "rewrite" - mode. The cookie will only be a session cookie and will not be - stored on the client's disk. By default, unless the "indirect" - option is added, the server will see the cookies emitted by the - client. Due to caching effects, it is generally wise to add the - "nocache" or "postonly" keywords (see below). The "insert" - keyword is not compatible with "rewrite" and "prefix". + server. When used without the "preserve" option, if the server + emits a cookie with the same name, it will be remove before + processing. For this reason, this mode can be used to upgrade + existing configurations running in the "rewrite" mode. The cookie + will only be a session cookie and will not be stored on the + client's disk. By default, unless the "indirect" option is added, + the server will see the cookies emitted by the client. Due to + caching effects, it is generally wise to add the "nocache" or + "postonly" keywords (see below). The "insert" keyword is not + compatible with "rewrite" and "prefix". prefix This keyword indicates that instead of relying on a dedicated cookie for the persistence, an existing one will be completed. @@ -1731,10 +1733,10 @@ cookie [ rewrite | insert | prefix ] [ indirect ] [ nocache ] indirect When this option is specified, no cookie will be emitted to a client which already has a valid one for the server which has processed the request. If the server sets such a cookie itself, - it will be removed. In "insert" mode, this will additionally - remove cookies from requests transmitted to the server, making - the persistence mechanism totally transparent from an application - point of view. + it will be removed, unless the "preserve" option is also set. In + "insert" mode, this will additionally remove cookies from the + requests transmitted to the server, making the persistence + mechanism totally transparent from an application point of view. nocache This option is recommended in conjunction with the insert mode when there is a cache between the client and HAProxy, as it @@ -1756,6 +1758,17 @@ cookie [ rewrite | insert | prefix ] [ indirect ] [ nocache ] persistence cookie in the cache. See also the "insert" and "nocache" options. + preserve This option may only be used with "insert" and/or "indirect". It + allows the server to emit the persistence cookie itself. In this + case, if a cookie is found in the response, haproxy will leave it + untouched. This is useful in order to end persistence after a + logout request for instance. For this, the server just has to + emit a cookie with an invalid value (eg: empty) or with a date in + the past. By combining this mechanism with the "disable-on-404" + check option, it is possible to perform a completely graceful + shutdown because users will definitely leave the server after + they logout. + domain This option allows to specify the domain at which a cookie is inserted. It requires exactly one parameter: a valid domain name. If the domain begins with a dot, the browser is allowed to diff --git a/include/types/proxy.h b/include/types/proxy.h index 246a9bed8e..f4fd4a921e 100644 --- a/include/types/proxy.h +++ b/include/types/proxy.h @@ -148,6 +148,7 @@ #define PR_O2_EXP_RSTR 0x02000000 /* http-check expect rstring */ #define PR_O2_EXP_TYPE 0x03800000 /* mask for http-check expect type */ #define PR_O2_EXP_INV 0x04000000 /* http-check expect ! */ +#define PR_O2_COOK_PSV 0x08000000 /* cookie ... preserve */ /* end of proxy->options2 */ /* bits for sticking rules */ diff --git a/src/cfgparse.c b/src/cfgparse.c index da6ef81a8c..a7cdea4d5a 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -1661,6 +1661,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) } curproxy->options &= ~PR_O_COOK_ANY; + curproxy->options2 &= ~PR_O2_COOK_PSV; curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0; free(curproxy->cookie_domain); curproxy->cookie_domain = NULL; free(curproxy->cookie_name); @@ -1684,6 +1685,9 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) else if (!strcmp(args[cur_arg], "postonly")) { curproxy->options |= PR_O_COOK_POST; } + else if (!strcmp(args[cur_arg], "preserve")) { + curproxy->options2 |= PR_O2_COOK_PSV; + } else if (!strcmp(args[cur_arg], "prefix")) { curproxy->options |= PR_O_COOK_PFX; } @@ -1790,6 +1794,12 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) file, linenum); err_code |= ERR_ALERT | ERR_FATAL; } + + if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) { + Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n", + file, linenum); + err_code |= ERR_ALERT | ERR_FATAL; + } }/* end else if (!strcmp(args[0], "cookie")) */ else if (!strcmp(args[0], "persist")) { /* persist */ if (*(args[1]) == 0) { diff --git a/src/proto_http.c b/src/proto_http.c index 3a2be18f75..a5e6e161e2 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -5098,6 +5098,7 @@ int http_process_res_common(struct session *t, struct buffer *rep, int an_bit, s * 6: add server cookie in the response if needed */ if ((t->srv) && (t->be->options & PR_O_COOK_INS) && + !((txn->flags & TX_SCK_FOUND) && (t->be->options2 & PR_O2_COOK_PSV)) && (!(t->flags & SN_DIRECT) || ((t->be->cookie_maxidle || txn->cookie_last_date) && (!txn->cookie_last_date || (txn->cookie_last_date - date.tv_sec) < 0)) || @@ -6780,7 +6781,12 @@ void manage_server_side_cookies(struct session *t, struct buffer *res) * We'll delete it too if the "indirect" option is set and we're in * a direct access. */ - if (((t->srv) && (t->be->options & PR_O_COOK_INS)) || + if (t->be->options2 & PR_O2_COOK_PSV) { + /* The "preserve" flag was set, we don't want to touch the + * server's cookie. + */ + } + else if (((t->srv) && (t->be->options & PR_O_COOK_INS)) || ((t->flags & SN_DIRECT) && (t->be->options & PR_O_COOK_IND))) { /* this cookie must be deleted */ if (*prev == ':' && next == hdr_end) {