[BUG] http: redirect rules were processed too early

redirect rules are documented as being processed last before
use_backend but were mistakenly processed before block rules.
Fortunately very few people use a mix of block and redirect
rules, so this bug has never been reported yet.
This commit is contained in:
Willy Tarreau 2009-07-06 16:34:52 +02:00
parent dc340a900d
commit 06b917c7ab
1 changed files with 106 additions and 106 deletions

View File

@ -1837,112 +1837,6 @@ int http_process_request(struct session *s, struct buffer *req)
struct proxy *rule_set = s->be;
cur_proxy = s->be;
/* first check whether we have some ACLs set to redirect this request */
list_for_each_entry(rule, &cur_proxy->redirect_rules, list) {
int ret = acl_exec_cond(rule->cond, cur_proxy, s, txn, ACL_DIR_REQ);
ret = acl_pass(ret);
if (rule->cond->pol == ACL_COND_UNLESS)
ret = !ret;
if (ret) {
struct chunk rdr = { trash, 0 };
const char *msg_fmt;
/* build redirect message */
switch(rule->code) {
case 303:
rdr.len = strlen(HTTP_303);
msg_fmt = HTTP_303;
break;
case 301:
rdr.len = strlen(HTTP_301);
msg_fmt = HTTP_301;
break;
case 302:
default:
rdr.len = strlen(HTTP_302);
msg_fmt = HTTP_302;
break;
}
if (unlikely(rdr.len > sizeof(trash)))
goto return_bad_req;
memcpy(rdr.str, msg_fmt, rdr.len);
switch(rule->type) {
case REDIRECT_TYPE_PREFIX: {
const char *path;
int pathlen;
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;
}
if (rdr.len + rule->rdr_len + pathlen > sizeof(trash) - 4)
goto return_bad_req;
/* add prefix. Note that if prefix == "/", we don't want to
* add anything, otherwise it makes it hard for the user to
* configure a self-redirection.
*/
if (rule->rdr_len != 1 || *rule->rdr_str != '/') {
memcpy(rdr.str + rdr.len, rule->rdr_str, rule->rdr_len);
rdr.len += rule->rdr_len;
}
/* add path */
memcpy(rdr.str + rdr.len, path, pathlen);
rdr.len += pathlen;
break;
}
case REDIRECT_TYPE_LOCATION:
default:
if (rdr.len + rule->rdr_len > sizeof(trash) - 4)
goto return_bad_req;
/* add location */
memcpy(rdr.str + rdr.len, rule->rdr_str, rule->rdr_len);
rdr.len += rule->rdr_len;
break;
}
if (rule->cookie_len) {
memcpy(rdr.str + rdr.len, "\r\nSet-Cookie: ", 14);
rdr.len += 14;
memcpy(rdr.str + rdr.len, rule->cookie_str, rule->cookie_len);
rdr.len += rule->cookie_len;
memcpy(rdr.str + rdr.len, "\r\n", 2);
rdr.len += 2;
}
/* add end of headers */
memcpy(rdr.str + rdr.len, "\r\n\r\n", 4);
rdr.len += 4;
txn->status = rule->code;
/* let's log the request time */
s->logs.tv_request = now;
stream_int_retnclose(req->prod, &rdr);
goto return_prx_cond;
}
}
/* first check whether we have some ACLs set to block this request */
list_for_each_entry(cond, &cur_proxy->block_cond, list) {
int ret = acl_exec_cond(cond, cur_proxy, s, txn, ACL_DIR_REQ);
@ -2059,6 +1953,112 @@ int http_process_request(struct session *s, struct buffer *req)
}
}
/* first check whether we have some ACLs set to redirect this request */
list_for_each_entry(rule, &cur_proxy->redirect_rules, list) {
int ret = acl_exec_cond(rule->cond, cur_proxy, s, txn, ACL_DIR_REQ);
ret = acl_pass(ret);
if (rule->cond->pol == ACL_COND_UNLESS)
ret = !ret;
if (ret) {
struct chunk rdr = { trash, 0 };
const char *msg_fmt;
/* build redirect message */
switch(rule->code) {
case 303:
rdr.len = strlen(HTTP_303);
msg_fmt = HTTP_303;
break;
case 301:
rdr.len = strlen(HTTP_301);
msg_fmt = HTTP_301;
break;
case 302:
default:
rdr.len = strlen(HTTP_302);
msg_fmt = HTTP_302;
break;
}
if (unlikely(rdr.len > sizeof(trash)))
goto return_bad_req;
memcpy(rdr.str, msg_fmt, rdr.len);
switch(rule->type) {
case REDIRECT_TYPE_PREFIX: {
const char *path;
int pathlen;
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;
}
if (rdr.len + rule->rdr_len + pathlen > sizeof(trash) - 4)
goto return_bad_req;
/* add prefix. Note that if prefix == "/", we don't want to
* add anything, otherwise it makes it hard for the user to
* configure a self-redirection.
*/
if (rule->rdr_len != 1 || *rule->rdr_str != '/') {
memcpy(rdr.str + rdr.len, rule->rdr_str, rule->rdr_len);
rdr.len += rule->rdr_len;
}
/* add path */
memcpy(rdr.str + rdr.len, path, pathlen);
rdr.len += pathlen;
break;
}
case REDIRECT_TYPE_LOCATION:
default:
if (rdr.len + rule->rdr_len > sizeof(trash) - 4)
goto return_bad_req;
/* add location */
memcpy(rdr.str + rdr.len, rule->rdr_str, rule->rdr_len);
rdr.len += rule->rdr_len;
break;
}
if (rule->cookie_len) {
memcpy(rdr.str + rdr.len, "\r\nSet-Cookie: ", 14);
rdr.len += 14;
memcpy(rdr.str + rdr.len, rule->cookie_str, rule->cookie_len);
rdr.len += rule->cookie_len;
memcpy(rdr.str + rdr.len, "\r\n", 2);
rdr.len += 2;
}
/* add end of headers */
memcpy(rdr.str + rdr.len, "\r\n\r\n", 4);
rdr.len += 4;
txn->status = rule->code;
/* let's log the request time */
s->logs.tv_request = now;
stream_int_retnclose(req->prod, &rdr);
goto return_prx_cond;
}
}
/* now check whether we have some switching rules for this request */
if (!(s->flags & SN_BE_ASSIGNED)) {
struct switching_rule *rule;