mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-06 23:27:04 +02:00
MINOR: http-ana: Add support for "set-cookie-fmt" option to redirect rules
It is now possible to use a log-format string to define the "Set-Cookie" header value of a response generated by a redirect rule. There is no special check on the result format and it is not possible during the configuration parsing. It is proably not a big deal because already existing "set-cookie" and "clear-cookie" options don't perform any check. Here is an example: http-request redirect location https://someurl.com/ set-cookie haproxy="%[var(txn.var)]" This patch should fix the issue #1784.
This commit is contained in:
parent
b2877db47c
commit
1be7140ade
@ -11453,6 +11453,12 @@ redirect scheme <sch> [code <code>] <option> [{if | unless} <condition>]
|
|||||||
that for a browser, a sole cookie name without an equal sign is
|
that for a browser, a sole cookie name without an equal sign is
|
||||||
different from a cookie with an equal sign.
|
different from a cookie with an equal sign.
|
||||||
|
|
||||||
|
- "set-cookie-fmt <fmt>"
|
||||||
|
It is equivaliant to the option above, except the "Set-Cookie" header
|
||||||
|
will be filled with the result of the log-format string <fmt>
|
||||||
|
evaluation. Be carefull to respect the "NAME[=value]" format because no
|
||||||
|
special check are performed during the configuration parsing.
|
||||||
|
|
||||||
- "clear-cookie NAME[=]"
|
- "clear-cookie NAME[=]"
|
||||||
A "Set-Cookie" header will be added with NAME (and optionally "="), but
|
A "Set-Cookie" header will be added with NAME (and optionally "="), but
|
||||||
with the "Max-Age" attribute set to zero. This will tell the browser to
|
with the "Max-Age" attribute set to zero. This will tell the browser to
|
||||||
|
@ -168,6 +168,7 @@ enum {
|
|||||||
REDIRECT_FLAG_FROM_REQ = 4, /* redirect rule on the request path */
|
REDIRECT_FLAG_FROM_REQ = 4, /* redirect rule on the request path */
|
||||||
REDIRECT_FLAG_IGNORE_EMPTY = 8, /* silently ignore empty location expressions */
|
REDIRECT_FLAG_IGNORE_EMPTY = 8, /* silently ignore empty location expressions */
|
||||||
REDIRECT_FLAG_KEEP_QS = 16, /* append the query string to location, if any */
|
REDIRECT_FLAG_KEEP_QS = 16, /* append the query string to location, if any */
|
||||||
|
REDIRECT_FLAG_COOKIE_FMT = 32, /* The cookie value is a log-format stirng*/
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Redirect types (location, prefix, extended ) */
|
/* Redirect types (location, prefix, extended ) */
|
||||||
|
@ -518,8 +518,10 @@ struct redirect_rule {
|
|||||||
struct lf_expr rdr_fmt;
|
struct lf_expr rdr_fmt;
|
||||||
int code;
|
int code;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
int cookie_len;
|
union {
|
||||||
char *cookie_str;
|
struct ist str; /* the cookie is a string */
|
||||||
|
struct lf_expr fmt; /* or a log-format string (possible for set-cookie only) */
|
||||||
|
} cookie;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* some of the most common options which are also the easiest to handle */
|
/* some of the most common options which are also the easiest to handle */
|
||||||
|
@ -2518,8 +2518,13 @@ int http_apply_redirect_rule(struct redirect_rule *rule, struct stream *s, struc
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rule->cookie_len) {
|
if (rule->flags & REDIRECT_FLAG_COOKIE_FMT) {
|
||||||
if (!htx_add_header(htx, ist("Set-Cookie"), ist2(rule->cookie_str, rule->cookie_len)))
|
trash.data = build_logline(s, trash.area, trash.size, &rule->cookie.fmt);
|
||||||
|
if (!htx_add_header(htx, ist("Set-Cookie"), ist2(trash.area, trash.data)))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
else if (isttest(rule->cookie.str)) {
|
||||||
|
if (!htx_add_header(htx, ist("Set-Cookie"), rule->cookie.str))
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,7 +322,10 @@ void http_free_redirect_rule(struct redirect_rule *rdr)
|
|||||||
{
|
{
|
||||||
free_acl_cond(rdr->cond);
|
free_acl_cond(rdr->cond);
|
||||||
free(rdr->rdr_str);
|
free(rdr->rdr_str);
|
||||||
free(rdr->cookie_str);
|
if ((rdr->flags & REDIRECT_FLAG_COOKIE_FMT))
|
||||||
|
lf_expr_deinit(&rdr->cookie.fmt);
|
||||||
|
else
|
||||||
|
istfree(&rdr->cookie.str);
|
||||||
lf_expr_deinit(&rdr->rdr_fmt);
|
lf_expr_deinit(&rdr->rdr_fmt);
|
||||||
free(rdr);
|
free(rdr);
|
||||||
}
|
}
|
||||||
@ -342,6 +345,7 @@ struct redirect_rule *http_parse_redirect_rule(const char *file, int linenum, st
|
|||||||
const char *destination = NULL;
|
const char *destination = NULL;
|
||||||
const char *cookie = NULL;
|
const char *cookie = NULL;
|
||||||
int cookie_set = 0;
|
int cookie_set = 0;
|
||||||
|
size_t cookie_len = 0;
|
||||||
unsigned int flags = (!dir ? REDIRECT_FLAG_FROM_REQ : REDIRECT_FLAG_NONE);
|
unsigned int flags = (!dir ? REDIRECT_FLAG_FROM_REQ : REDIRECT_FLAG_NONE);
|
||||||
struct acl_cond *cond = NULL;
|
struct acl_cond *cond = NULL;
|
||||||
|
|
||||||
@ -378,6 +382,14 @@ struct redirect_rule *http_parse_redirect_rule(const char *file, int linenum, st
|
|||||||
cookie = args[cur_arg];
|
cookie = args[cur_arg];
|
||||||
cookie_set = 1;
|
cookie_set = 1;
|
||||||
}
|
}
|
||||||
|
else if (strcmp(args[cur_arg], "set-cookie-fmt") == 0) {
|
||||||
|
if (!*args[cur_arg + 1])
|
||||||
|
goto missing_arg;
|
||||||
|
|
||||||
|
cur_arg++;
|
||||||
|
cookie = args[cur_arg];
|
||||||
|
cookie_set = 2;
|
||||||
|
}
|
||||||
else if (strcmp(args[cur_arg], "clear-cookie") == 0) {
|
else if (strcmp(args[cur_arg], "clear-cookie") == 0) {
|
||||||
if (!*args[cur_arg + 1])
|
if (!*args[cur_arg + 1])
|
||||||
goto missing_arg;
|
goto missing_arg;
|
||||||
@ -422,7 +434,8 @@ struct redirect_rule *http_parse_redirect_rule(const char *file, int linenum, st
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
memprintf(errmsg,
|
memprintf(errmsg,
|
||||||
"expects 'code', 'prefix', 'location', 'scheme', 'set-cookie', 'clear-cookie', 'drop-query', 'keep-query', 'ignore-empty' or 'append-slash' (was '%s')",
|
"expects 'code', 'prefix', 'location', 'scheme', 'set-cookie', 'set-cookie-fmt',"
|
||||||
|
" 'clear-cookie', 'drop-query', 'keep-query', 'ignore-empty' or 'append-slash' (was '%s')",
|
||||||
args[cur_arg]);
|
args[cur_arg]);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@ -476,21 +489,38 @@ struct redirect_rule *http_parse_redirect_rule(const char *file, int linenum, st
|
|||||||
/* depending on cookie_set, either we want to set the cookie, or to clear it.
|
/* depending on cookie_set, either we want to set the cookie, or to clear it.
|
||||||
* a clear consists in appending "; path=/; Max-Age=0;" at the end.
|
* a clear consists in appending "; path=/; Max-Age=0;" at the end.
|
||||||
*/
|
*/
|
||||||
rule->cookie_len = strlen(cookie);
|
cookie_len = strlen(cookie);
|
||||||
if (cookie_set) {
|
if (cookie_set == 1) { // set-cookie
|
||||||
rule->cookie_str = malloc(rule->cookie_len + 10);
|
rule->cookie.str = istalloc(cookie_len+9);
|
||||||
if (!rule->cookie_str)
|
if (!isttest(rule->cookie.str))
|
||||||
goto out_of_memory;
|
goto out_of_memory;
|
||||||
memcpy(rule->cookie_str, cookie, rule->cookie_len);
|
istcpy(&rule->cookie.str, ist2(cookie, cookie_len), cookie_len);
|
||||||
memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
|
istcat(&rule->cookie.str, ist2("; path=/;", 9), cookie_len+10);
|
||||||
rule->cookie_len += 9;
|
}
|
||||||
} else {
|
else if (cookie_set == 2) { // set-cookie-fmt
|
||||||
rule->cookie_str = malloc(rule->cookie_len + 21);
|
int cap = 0;
|
||||||
if (!rule->cookie_str)
|
|
||||||
|
lf_expr_init(&rule->cookie.fmt);
|
||||||
|
curproxy->conf.args.ctx = ARGC_RDR;
|
||||||
|
if (curproxy->cap & PR_CAP_FE)
|
||||||
|
cap |= (dir ? SMP_VAL_FE_HRS_HDR : SMP_VAL_FE_HRQ_HDR);
|
||||||
|
if (curproxy->cap & PR_CAP_BE)
|
||||||
|
cap |= (dir ? SMP_VAL_BE_HRS_HDR : SMP_VAL_BE_HRQ_HDR);
|
||||||
|
|
||||||
|
chunk_memcpy(&trash, cookie, cookie_len);
|
||||||
|
chunk_strcat(&trash, "; path=/;");
|
||||||
|
if (!parse_logformat_string(trash.area, curproxy, &rule->cookie.fmt, LOG_OPT_HTTP, cap, errmsg)) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
flags |= REDIRECT_FLAG_COOKIE_FMT;
|
||||||
|
}
|
||||||
|
else { // clear-cookie
|
||||||
|
rule->cookie.str = istalloc(cookie_len+20);
|
||||||
|
if (!isttest(rule->cookie.str))
|
||||||
goto out_of_memory;
|
goto out_of_memory;
|
||||||
memcpy(rule->cookie_str, cookie, rule->cookie_len);
|
istcpy(&rule->cookie.str, ist2(cookie, cookie_len), cookie_len);
|
||||||
memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
|
istcat(&rule->cookie.str, ist2("; path=/; Max-Age=0;", 20), cookie_len+21);
|
||||||
rule->cookie_len += 20;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rule->type = type;
|
rule->type = type;
|
||||||
|
Loading…
Reference in New Issue
Block a user