mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-24 23:31:40 +02:00
MEDIUM: http: add "redirect scheme" to ease HTTP to HTTPS redirection
For instance : redirect scheme https if !{ is_ssl }
This commit is contained in:
parent
16216828fc
commit
2e1dca8f52
@ -4393,8 +4393,9 @@ rate-limit sessions <rate>
|
|||||||
See also : the "backlog" keyword and the "fe_sess_rate" ACL criterion.
|
See also : the "backlog" keyword and the "fe_sess_rate" ACL criterion.
|
||||||
|
|
||||||
|
|
||||||
redirect location <to> [code <code>] <option> [{if | unless} <condition>]
|
redirect location <loc> [code <code>] <option> [{if | unless} <condition>]
|
||||||
redirect prefix <to> [code <code>] <option> [{if | unless} <condition>]
|
redirect prefix <pfx> [code <code>] <option> [{if | unless} <condition>]
|
||||||
|
redirect scheme <sch> [code <code>] <option> [{if | unless} <condition>]
|
||||||
Return an HTTP redirection if/unless a condition is matched
|
Return an HTTP redirection if/unless a condition is matched
|
||||||
May be used in sections : defaults | frontend | listen | backend
|
May be used in sections : defaults | frontend | listen | backend
|
||||||
no | yes | yes | yes
|
no | yes | yes | yes
|
||||||
@ -4403,14 +4404,25 @@ redirect prefix <to> [code <code>] <option> [{if | unless} <condition>]
|
|||||||
response. If no condition is specified, the redirect applies unconditionally.
|
response. If no condition is specified, the redirect applies unconditionally.
|
||||||
|
|
||||||
Arguments :
|
Arguments :
|
||||||
<to> With "redirect location", the exact value in <to> is placed into
|
<loc> With "redirect location", the exact value in <loc> is placed into
|
||||||
the HTTP "Location" header. In case of "redirect prefix", the
|
the HTTP "Location" header.
|
||||||
"Location" header is built from the concatenation of <to> and the
|
|
||||||
complete URI, including the query string, unless the "drop-query"
|
<pfx> With "redirect prefix", the "Location" header is built from the
|
||||||
option is specified (see below). As a special case, if <to>
|
concatenation of <pfx> and the complete URI path, including the
|
||||||
equals exactly "/" in prefix mode, then nothing is inserted
|
query string, unless the "drop-query" option is specified (see
|
||||||
before the original URI. It allows one to redirect to the same
|
below). As a special case, if <pfx> equals exactly "/", then
|
||||||
URL.
|
nothing is inserted before the original URI. It allows one to
|
||||||
|
redirect to the same URL (for instance, to insert a cookie).
|
||||||
|
|
||||||
|
<sch> With "redirect scheme", then the "Location" header is built by
|
||||||
|
concatenating <sch> with "://" then the first occurrence of the
|
||||||
|
"Host" header, and then the URI path, including the query string
|
||||||
|
unless the "drop-query" option is specified (see below). If no
|
||||||
|
path is found or if the path is "*", then "/" is used instead. If
|
||||||
|
no "Host" header is found, then an empty host component will be
|
||||||
|
returned, which most recent browsers interprete as redirecting to
|
||||||
|
the same host. This directive is mostly used to redirect HTTP to
|
||||||
|
HTTPS.
|
||||||
|
|
||||||
<code> The code is optional. It indicates which type of HTTP redirection
|
<code> The code is optional. It indicates which type of HTTP redirection
|
||||||
is desired. Only codes 301, 302 and 303 are supported, and 302 is
|
is desired. Only codes 301, 302 and 303 are supported, and 302 is
|
||||||
@ -4469,6 +4481,9 @@ redirect prefix <to> [code <code>] <option> [{if | unless} <condition>]
|
|||||||
acl missing_slash path_reg ^/article/[^/]*$
|
acl missing_slash path_reg ^/article/[^/]*$
|
||||||
redirect code 301 prefix / drop-query append-slash if missing_slash
|
redirect code 301 prefix / drop-query append-slash if missing_slash
|
||||||
|
|
||||||
|
Example: redirect all HTTP traffic to HTTPS when SSL is handled by haproxy.
|
||||||
|
redirect scheme https if !{ is_ssl }
|
||||||
|
|
||||||
See section 7 about ACL usage.
|
See section 7 about ACL usage.
|
||||||
|
|
||||||
|
|
||||||
|
@ -204,6 +204,7 @@ enum {
|
|||||||
REDIRECT_TYPE_NONE = 0, /* no redirection */
|
REDIRECT_TYPE_NONE = 0, /* no redirection */
|
||||||
REDIRECT_TYPE_LOCATION, /* location redirect */
|
REDIRECT_TYPE_LOCATION, /* location redirect */
|
||||||
REDIRECT_TYPE_PREFIX, /* prefix redirect */
|
REDIRECT_TYPE_PREFIX, /* prefix redirect */
|
||||||
|
REDIRECT_TYPE_SCHEME, /* scheme redirect (eg: switch from http to https) */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Perist types (force-persist, ignore-persist) */
|
/* Perist types (force-persist, ignore-persist) */
|
||||||
|
@ -2837,6 +2837,18 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
|||||||
cur_arg++;
|
cur_arg++;
|
||||||
destination = args[cur_arg];
|
destination = args[cur_arg];
|
||||||
}
|
}
|
||||||
|
else if (!strcmp(args[cur_arg], "scheme")) {
|
||||||
|
if (!*args[cur_arg + 1]) {
|
||||||
|
Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
|
||||||
|
file, linenum, args[0], args[cur_arg]);
|
||||||
|
err_code |= ERR_ALERT | ERR_FATAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
type = REDIRECT_TYPE_SCHEME;
|
||||||
|
cur_arg++;
|
||||||
|
destination = args[cur_arg];
|
||||||
|
}
|
||||||
else if (!strcmp(args[cur_arg], "set-cookie")) {
|
else if (!strcmp(args[cur_arg], "set-cookie")) {
|
||||||
if (!*args[cur_arg + 1]) {
|
if (!*args[cur_arg + 1]) {
|
||||||
Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
|
Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
|
||||||
@ -2895,7 +2907,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
|
Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'scheme', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
|
||||||
file, linenum, args[0], args[cur_arg]);
|
file, linenum, args[0], args[cur_arg]);
|
||||||
err_code |= ERR_ALERT | ERR_FATAL;
|
err_code |= ERR_ALERT | ERR_FATAL;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -3072,6 +3072,71 @@ int http_process_req_common(struct session *s, struct channel *req, int an_bit,
|
|||||||
goto return_bad_req;
|
goto return_bad_req;
|
||||||
|
|
||||||
switch(rule->type) {
|
switch(rule->type) {
|
||||||
|
case REDIRECT_TYPE_SCHEME: {
|
||||||
|
const char *path;
|
||||||
|
const char *host;
|
||||||
|
struct hdr_ctx ctx;
|
||||||
|
int pathlen;
|
||||||
|
int hostlen;
|
||||||
|
|
||||||
|
host = "";
|
||||||
|
hostlen = 0;
|
||||||
|
ctx.idx = 0;
|
||||||
|
if (http_find_header2("Host", 4, txn->req.buf->buf.p + txn->req.sol, &txn->hdr_idx, &ctx)) {
|
||||||
|
host = ctx.line + ctx.val;
|
||||||
|
hostlen = ctx.vlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
path = http_get_path(txn);
|
||||||
|
/* build message using path */
|
||||||
|
if (path) {
|
||||||
|
pathlen = txn->req.sl.rq.u_l + (req->buf.p + txn->req.sl.rq.u) - path;
|
||||||
|
if (rule->flags & REDIRECT_FLAG_DROP_QS) {
|
||||||
|
int qs = 0;
|
||||||
|
while (qs < pathlen) {
|
||||||
|
if (path[qs] == '?') {
|
||||||
|
pathlen = qs;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
qs++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
path = "/";
|
||||||
|
pathlen = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if we can add scheme + "://" + host + path */
|
||||||
|
if (rdr.len + rule->rdr_len + 3 + hostlen + pathlen > rdr.size - 4)
|
||||||
|
goto return_bad_req;
|
||||||
|
|
||||||
|
/* add scheme */
|
||||||
|
memcpy(rdr.str + rdr.len, rule->rdr_str, rule->rdr_len);
|
||||||
|
rdr.len += rule->rdr_len;
|
||||||
|
|
||||||
|
/* add "://" */
|
||||||
|
memcpy(rdr.str + rdr.len, "://", 3);
|
||||||
|
rdr.len += 3;
|
||||||
|
|
||||||
|
/* add host */
|
||||||
|
memcpy(rdr.str + rdr.len, host, hostlen);
|
||||||
|
rdr.len += hostlen;
|
||||||
|
|
||||||
|
/* add path */
|
||||||
|
memcpy(rdr.str + rdr.len, path, pathlen);
|
||||||
|
rdr.len += pathlen;
|
||||||
|
|
||||||
|
/* append a slash at the end of the location is needed and missing */
|
||||||
|
if (rdr.len && rdr.str[rdr.len - 1] != '/' &&
|
||||||
|
(rule->flags & REDIRECT_FLAG_APPEND_SLASH)) {
|
||||||
|
if (rdr.len > rdr.size - 5)
|
||||||
|
goto return_bad_req;
|
||||||
|
rdr.str[rdr.len] = '/';
|
||||||
|
rdr.len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case REDIRECT_TYPE_PREFIX: {
|
case REDIRECT_TYPE_PREFIX: {
|
||||||
const char *path;
|
const char *path;
|
||||||
int pathlen;
|
int pathlen;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user