[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)
This commit is contained in:
Willy Tarreau 2010-10-23 12:46:42 +02:00
parent c63d4bbff9
commit ba4c5be880
4 changed files with 45 additions and 15 deletions

View file

@ -1675,7 +1675,7 @@ contimeout <timeout> (deprecated)
cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ]
[ postonly ] [ domain <domain> ]*
[ postonly ] [ preserve ] [ domain <domain> ]*
[ maxidle <idle> ] [ maxlife <life> ]
Enable cookie-based persistence in a backend.
May be used in sections : defaults | frontend | listen | backend
@ -1705,16 +1705,18 @@ cookie <name> [ 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 <name> [ 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 <name> [ 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

View file

@ -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 !<rule> */
#define PR_O2_COOK_PSV 0x08000000 /* cookie ... preserve */
/* end of proxy->options2 */
/* bits for sticking rules */

View file

@ -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) {

View file

@ -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) {