]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MINOR] cookie: add support for the "preserve" option
authorWilly Tarreau <w@1wt.eu>
Sat, 23 Oct 2010 10:46:42 +0000 (12:46 +0200)
committerWilly Tarreau <w@1wt.eu>
Sat, 30 Oct 2010 17:04:36 +0000 (19:04 +0200)
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)

doc/configuration.txt
include/types/proxy.h
src/cfgparse.c
src/proto_http.c

index d05ad9ea59704fe236f52b0e380b37fabc2ab519..ae4827a88af921d6dd56109c4cc1f16996dea0a6 100644 (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
index 246a9bed8e986155ffd1d93de2e5368bf726a083..f4fd4a921e1ab4093bffef9a43631bfc68d50b82 100644 (file)
 #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 */
index da6ef81a8cf5b5769eb277e8b12500a256167440..a7cdea4d5a68931b1b8b1da79a2237191a594fa8 100644 (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) {
index 3a2be18f7532f03c6bf3ab585bf822b7f279ee30..a5e6e161e28252ad2c8b9493e1a7996c01be545e 100644 (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) {