[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.
diff --git a/src/proto_http.c b/src/proto_http.c
index a8612a4..86af03d 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -1837,112 +1837,6 @@
 		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 @@
 			}
 		}
 
+		/* 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;