Hi Willy, Yikes, sorry about the mangled patch -- not sure what happened there... Thanks for bringing this into the 1.4 line, though!
rusty On Mon, Nov 18, 2013 at 1:25 AM, Willy Tarreau <[email protected]> wrote: > Hi Russell, > > On Fri, Nov 15, 2013 at 07:37:31PM -0500, Russell Geldmacher wrote: >> Hi everyone, >> >> Recently we've had a requirement come through that could be >> implemented quite nicely using 1.5-dev's 'redirect scheme' >> functionality. However, (understandably) policies prevent us from >> running a dev version in production. >> >> I found the original patch that Willy posted for this functionality >> (http://marc.info/?l=haproxy&m=134743247117173) and adjusted it so >> that it applies and runs under 1.4.24. >> >> Not sure if you guys accept backport patches but I just wanted to get >> this out there in case other folks were searching for the same thing. > > That seems reasonably low impact, yes. However your patch was mangled, > all spaces and tabs used for indenting were removed by your mail agent > as you can see below. So I have just cherry-picked it again and it's > now OK. > > Regards, > Willy > >> --------------------- >> >> diff -urb haproxy-1.4.24/doc/configuration.txt >> haproxy-1.4.24-scheme/doc/configuration.txt >> --- a/doc/configuration.txt 2013-06-17 09:28:14.000000000 -0400 >> +++ b/doc/configuration.txt 2013-11-15 19:15:58.000000000 -0500 >> @@ -4039,8 +4039,9 @@ >> See also : the "backlog" keyword and the "fe_sess_rate" ACL criterion. >> >> >> -redirect location <to> [code <code>] <option> [{if | unless} <condition>] >> -redirect prefix <to> [code <code>] <option> [{if | unless} <condition>] >> +redirect location <loc> [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 >> May be used in sections : defaults | frontend | listen | backend >> no | yes | yes | yes >> @@ -4049,14 +4050,25 @@ >> response. If no condition is specified, the redirect applies >> unconditionally. >> >> Arguments : >> - <to> With "redirect location", the exact value in <to> is placed >> into >> - the HTTP "Location" header. In case of "redirect prefix", the >> - "Location" header is built from the concatenation of <to> and >> the >> - complete URI, including the query string, unless the >> "drop-query" >> - option is specified (see below). As a special case, if <to> >> - equals exactly "/" in prefix mode, then nothing is inserted >> - before the original URI. It allows one to redirect to the same >> - URL. >> + <loc> With "redirect location", the exact value in <loc> is placed >> into >> + the HTTP "Location" header. >> + >> + <pfx> With "redirect prefix", the "Location" header is built from >> the >> + concatenation of <pfx> and the complete URI path, including >> the >> + query string, unless the "drop-query" option is specified (see >> + below). As a special case, if <pfx> equals exactly "/", then >> + 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 >> is desired. Only codes 301, 302, 303, 307 and 308 are >> supported, >> diff -urb haproxy-1.4.24/include/types/proto_http.h >> haproxy-1.4.24-scheme/include/types/proto_http.h >> --- a/include/types/proto_http.h 2013-06-17 09:28:14.000000000 -0400 >> +++ b/include/types/proto_http.h 2013-11-15 19:11:48.000000000 -0500 >> @@ -224,6 +224,7 @@ >> REDIRECT_TYPE_NONE = 0, /* no redirection */ >> REDIRECT_TYPE_LOCATION, /* location redirect */ >> REDIRECT_TYPE_PREFIX, /* prefix redirect */ >> + REDIRECT_TYPE_SCHEME, /* scheme redirect (eg: switch from >> http to https) */ >> }; >> >> /* Perist types (force-persist, ignore-persist) */ >> diff -urb haproxy-1.4.24/src/cfgparse.c haproxy-1.4.24-scheme/src/cfgparse.c >> --- a/src/cfgparse.c 2013-06-17 09:28:14.000000000 -0400 >> +++ b/src/cfgparse.c 2013-11-15 19:19:10.000000000 -0500 >> @@ -2182,6 +2182,18 @@ >> 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")) { >> if (!*args[cur_arg + 1]) { >> Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n", >> @@ -2240,7 +2252,7 @@ >> break; >> } >> 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]); >> err_code |= ERR_ALERT | ERR_FATAL; >> goto out; >> diff -urb haproxy-1.4.24/src/proto_http.c >> haproxy-1.4.24-scheme/src/proto_http.c >> --- a/src/proto_http.c 2013-06-17 09:28:14.000000000 -0400 >> +++ b/src/proto_http.c 2013-11-15 19:11:48.000000000 -0500 >> @@ -3390,6 +3390,71 @@ >> goto return_bad_req; >> >> 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, msg->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 + (txn->req.sol + 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: { >> const char *path; >> int pathlen;

