MINOR: http-ana: Add option to keep query-string on a localtion-based redirect

On prefix-based redirect, there is an option to drop the query-string of the
location. Here it is the opposite. an option is added to preserve the
query-string of the original URI for a localtion-based redirect.

By setting "keep-query" option, for a location-based redirect only, the
query-string of the original URI is appended to the location. If there is no
query-string, nothing is added (no empty '?'). If there is already a
non-empty query-string on the localtion, the original one is appended with
'&' separator.

This patch should fix issue #2728.
This commit is contained in:
Christopher Faulet 2024-11-15 17:03:06 +01:00
parent 7848692c4c
commit b2877db47c
4 changed files with 44 additions and 1 deletions

View File

@ -11461,6 +11461,14 @@ redirect scheme <sch> [code <code>] <option> [{if | unless} <condition>]
cookie set with "NAME=value". You have to clear the cookie "NAME=" for
that, because the browser makes the difference.
- "keep-query"
When this keyword is used in a location-based redirection, then the
query-string of the original URI, if any, will be appended to the
location. If no query-string is found, nothing is added. If the
location already contains a query-string, the original one will be
appended with the '&' delimiter.
Example: move the login URL only to HTTPS.
acl clear dst_port 80
acl secure dst_port 8080

View File

@ -167,6 +167,7 @@ enum {
REDIRECT_FLAG_APPEND_SLASH = 2, /* append a slash if missing at the end */
REDIRECT_FLAG_FROM_REQ = 4, /* redirect rule on the request path */
REDIRECT_FLAG_IGNORE_EMPTY = 8, /* silently ignore empty location expressions */
REDIRECT_FLAG_KEEP_QS = 16, /* append the query string to location, if any */
};
/* Redirect types (location, prefix, extended ) */

View File

@ -2420,6 +2420,7 @@ int http_apply_redirect_rule(struct redirect_rule *rule, struct stream *s, struc
}
case REDIRECT_TYPE_LOCATION:
default:
memset(chunk->area, 0x50, chunk->size);
if (rule->rdr_str) { /* this is an old "redirect" rule */
/* add location */
if (!chunk_memcat(chunk, rule->rdr_str, rule->rdr_len))
@ -2437,6 +2438,36 @@ int http_apply_redirect_rule(struct redirect_rule *rule, struct stream *s, struc
chunk->data += len;
}
if (rule->flags & REDIRECT_FLAG_KEEP_QS) {
struct ist path;
struct http_uri_parser parser;
char *ptr, *end;
char sep = '?';
ptr = memchr(chunk->area, '?', chunk->data);
if (ptr != NULL)
sep = ((ptr+1 != b_tail(chunk)) ? '&' : '\0');
sl = http_get_stline(htx);
parser = http_uri_parser_init(htx_sl_req_uri(sl));
path = http_parse_path(&parser);
ptr = istptr(path);
end = istend(path);
/* look up the '?' */
do {
if (ptr == end)
return 0;
} while (*ptr++ != '?');
if (ptr == end)
break;
if (sep != '\0' && !chunk_memcat(chunk, &sep, 1))
goto fail;
if (!chunk_memcat(chunk, ptr, end-ptr))
goto fail;
}
break;
}
location = ist2(chunk->area, chunk->data);

View File

@ -402,6 +402,9 @@ struct redirect_rule *http_parse_redirect_rule(const char *file, int linenum, st
else if (strcmp(args[cur_arg], "drop-query") == 0) {
flags |= REDIRECT_FLAG_DROP_QS;
}
else if (strcmp(args[cur_arg], "keep-query") == 0) {
flags |= REDIRECT_FLAG_KEEP_QS;
}
else if (strcmp(args[cur_arg], "append-slash") == 0) {
flags |= REDIRECT_FLAG_APPEND_SLASH;
}
@ -419,7 +422,7 @@ struct redirect_rule *http_parse_redirect_rule(const char *file, int linenum, st
}
else {
memprintf(errmsg,
"expects 'code', 'prefix', 'location', 'scheme', 'set-cookie', 'clear-cookie', 'drop-query', 'ignore-empty' or 'append-slash' (was '%s')",
"expects 'code', 'prefix', 'location', 'scheme', 'set-cookie', 'clear-cookie', 'drop-query', 'keep-query', 'ignore-empty' or 'append-slash' (was '%s')",
args[cur_arg]);
goto err;
}