mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-02-17 02:56:51 +00:00
MEDIUM: http: add support for "http-request redirect" rules
These are exactly the same as the classic redirect rules except that they can be interleaved with other http-request rules for more flexibility. The redirect parser should probably be changed to stop at the condition so that the caller puts its own condition pointer. At the moment, the redirect rule and condition are parsed at once by build_redirect_rule() and the condition is assigned to the http_req_rule.
This commit is contained in:
parent
4baae248fc
commit
81499eb67d
@ -2606,7 +2606,7 @@ http-check send-state
|
||||
|
||||
See also : "option httpchk", "http-check disable-on-404"
|
||||
|
||||
http-request { allow | deny | auth [realm <realm>] |
|
||||
http-request { allow | deny | auth [realm <realm>] | redirect <rule> |
|
||||
add-header <name> <fmt> | set-header <name> <fmt> }
|
||||
[ { if | unless } <condition> ]
|
||||
Access control for Layer 7 requests
|
||||
@ -2634,6 +2634,11 @@ http-request { allow | deny | auth [realm <realm>] |
|
||||
optional "realm" parameter is supported, it sets the authentication realm
|
||||
that is returned with the response (typically the application's name).
|
||||
|
||||
- "redirect" : this performs an HTTP redirection based on a redirect rule.
|
||||
This is exactly the same as the "redirect" statement except that it
|
||||
inserts a redirect rule which can be processed in the middle of other
|
||||
"http-request" rules. See the "redirect" keyword for the rule's syntax.
|
||||
|
||||
- "add-header" appends an HTTP header field whose name is specified in
|
||||
<name> and whose value is defined by <fmt> which follows the log-format
|
||||
rules (see Custom Log Format in section 8.2.4). This is particularly
|
||||
|
@ -243,6 +243,7 @@ enum {
|
||||
HTTP_REQ_ACT_AUTH,
|
||||
HTTP_REQ_ACT_ADD_HDR,
|
||||
HTTP_REQ_ACT_SET_HDR,
|
||||
HTTP_REQ_ACT_REDIR,
|
||||
HTTP_REQ_ACT_MAX /* must always be last */
|
||||
};
|
||||
|
||||
@ -354,6 +355,7 @@ struct http_req_rule {
|
||||
int name_len; /* header name's length */
|
||||
struct list fmt; /* log-format compatible expression */
|
||||
} hdr_add; /* args used by "add-header" and "set-header" */
|
||||
struct redirect_rule *redir; /* redirect rule or "http-request redirect" */
|
||||
} arg; /* arguments used by some actions */
|
||||
};
|
||||
|
||||
|
@ -3104,6 +3104,9 @@ http_req_get_intercept_rule(struct proxy *px, struct list *rules, struct session
|
||||
case HTTP_REQ_ACT_AUTH:
|
||||
return rule;
|
||||
|
||||
case HTTP_REQ_ACT_REDIR:
|
||||
return rule;
|
||||
|
||||
case HTTP_REQ_ACT_SET_HDR:
|
||||
ctx.idx = 0;
|
||||
/* remove all occurrences of the header */
|
||||
@ -3552,6 +3555,13 @@ int http_process_req_common(struct session *s, struct channel *req, int an_bit,
|
||||
goto return_bad_req;
|
||||
}
|
||||
|
||||
if (http_req_last_rule && http_req_last_rule->action == HTTP_REQ_ACT_REDIR) {
|
||||
if (!http_apply_redirect_rule(http_req_last_rule->arg.redir, s, txn))
|
||||
goto return_bad_req;
|
||||
req->analyse_exp = TICK_ETERNITY;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (unlikely(do_stats)) {
|
||||
/* process the stats request now */
|
||||
if (!http_handle_stats(s, req)) {
|
||||
@ -8040,7 +8050,7 @@ struct http_req_rule *parse_http_req_cond(const char **args, const char *file, i
|
||||
rule = (struct http_req_rule*)calloc(1, sizeof(struct http_req_rule));
|
||||
if (!rule) {
|
||||
Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
|
||||
return NULL;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (!strcmp(args[0], "allow")) {
|
||||
@ -8068,7 +8078,7 @@ struct http_req_rule *parse_http_req_cond(const char **args, const char *file, i
|
||||
if (!*args[cur_arg] || !*args[cur_arg+1] || *args[cur_arg+2]) {
|
||||
Alert("parsing [%s:%d]: 'http-request %s' expects exactly 2 arguments.\n",
|
||||
file, linenum, args[0]);
|
||||
return NULL;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
rule->arg.hdr_add.name = strdup(args[cur_arg]);
|
||||
@ -8076,10 +8086,29 @@ struct http_req_rule *parse_http_req_cond(const char **args, const char *file, i
|
||||
LIST_INIT(&rule->arg.hdr_add.fmt);
|
||||
parse_logformat_string(args[cur_arg + 1], proxy, &rule->arg.hdr_add.fmt, PR_MODE_HTTP);
|
||||
cur_arg += 2;
|
||||
} else if (strcmp(args[0], "redirect") == 0) {
|
||||
struct redirect_rule *redir;
|
||||
char *errmsg;
|
||||
|
||||
if ((redir = http_parse_redirect_rule(file, linenum, proxy, (const char **)args + 1, &errmsg)) == NULL) {
|
||||
Alert("parsing [%s:%d] : error detected in %s '%s' while parsing 'http-request %s' rule : %s.\n",
|
||||
file, linenum, proxy_type_str(proxy), proxy->id, args[0], errmsg);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
/* this redirect rule might already contain a parsed condition which
|
||||
* we'll pass to the http-request rule.
|
||||
*/
|
||||
rule->action = HTTP_REQ_ACT_REDIR;
|
||||
rule->arg.redir = redir;
|
||||
rule->cond = redir->cond;
|
||||
redir->cond = NULL;
|
||||
cur_arg = 2;
|
||||
return rule;
|
||||
} else {
|
||||
Alert("parsing [%s:%d]: 'http-request' expects 'allow', 'deny', 'auth', 'add-header', 'set-header', but got '%s'%s.\n",
|
||||
file, linenum, args[0], *args[0] ? "" : " (missing argument)");
|
||||
return NULL;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (strcmp(args[cur_arg], "if") == 0 || strcmp(args[cur_arg], "unless") == 0) {
|
||||
@ -8090,7 +8119,7 @@ struct http_req_rule *parse_http_req_cond(const char **args, const char *file, i
|
||||
Alert("parsing [%s:%d] : error detected while parsing an 'http-request %s' condition : %s.\n",
|
||||
file, linenum, args[0], errmsg);
|
||||
free(errmsg);
|
||||
return NULL;
|
||||
goto out_err;
|
||||
}
|
||||
rule->cond = cond;
|
||||
}
|
||||
@ -8098,10 +8127,13 @@ struct http_req_rule *parse_http_req_cond(const char **args, const char *file, i
|
||||
Alert("parsing [%s:%d]: 'http-request %s' expects 'realm' for 'auth' or"
|
||||
" either 'if' or 'unless' followed by a condition but found '%s'.\n",
|
||||
file, linenum, args[0], args[cur_arg]);
|
||||
return NULL;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
return rule;
|
||||
out_err:
|
||||
free(rule);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Parses a redirect rule. Returns the redirect rule on success or NULL on error,
|
||||
|
Loading…
Reference in New Issue
Block a user