static void http_debug_stline(const char *dir, struct stream *s, const struct htx_sl *sl);
static void http_debug_hdr(const char *dir, struct stream *s, const struct ist n, const struct ist v);
-static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct list *rules, struct stream *s);
-static enum rule_result http_res_get_intercept_rule(struct proxy *px, struct list *rules, struct stream *s);
+static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct list *def_rules, struct list *rules, struct stream *s);
+static enum rule_result http_res_get_intercept_rule(struct proxy *px, struct list *def_rules, struct list *rules, struct stream *s);
static void http_manage_client_side_cookies(struct stream *s, struct channel *req);
static void http_manage_server_side_cookies(struct stream *s, struct channel *res);
*/
int http_process_req_common(struct stream *s, struct channel *req, int an_bit, struct proxy *px)
{
+ struct list *def_rules, *rules;
struct session *sess = s->sess;
struct http_txn *txn = s->txn;
struct http_msg *msg = &txn->req;
/* just in case we have some per-backend tracking. Only called the first
* execution of the analyser. */
- if (!s->current_rule || s->current_rule_list != &px->http_req_rules)
+ if (!s->current_rule && !s->current_rule_list)
stream_inc_be_http_req_ctr(s);
+ def_rules = ((px->defpx && (an_bit == AN_REQ_HTTP_PROCESS_FE || px != sess->fe)) ? &px->defpx->http_req_rules : NULL);
+ rules = &px->http_req_rules;
+
/* evaluate http-request rules */
- if (!LIST_ISEMPTY(&px->http_req_rules)) {
- verdict = http_req_get_intercept_rule(px, &px->http_req_rules, s);
+ if ((def_rules && !LIST_ISEMPTY(def_rules)) || !LIST_ISEMPTY(rules)) {
+ verdict = http_req_get_intercept_rule(px, def_rules, rules, s);
switch (verdict) {
case HTTP_RULE_RES_YIELD: /* some data miss, call the function later. */
/* parse the whole stats request and extract the relevant information */
http_handle_stats(s, req);
- verdict = http_req_get_intercept_rule(px, &px->uri_auth->http_req_rules, s);
+ verdict = http_req_get_intercept_rule(px, NULL, &px->uri_auth->http_req_rules, s);
/* not all actions implemented: deny, allow, auth */
if (verdict == HTTP_RULE_RES_DENY) /* stats http-request deny */
req->analyse_exp = TICK_ETERNITY;
done_without_exp: /* done with this analyser, but don't reset the analyse_exp. */
req->analysers &= ~an_bit;
+ s->current_rule = s->current_rule_list = NULL;
DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 1;
req->analysers &= AN_REQ_FLT_END;
req->analyse_exp = TICK_ETERNITY;
+ s->current_rule = s->current_rule_list = NULL;
DBG_TRACE_DEVEL("leaving on error",
STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_HTTP_ERR, s, txn);
return 0;
* pointer and the ->fe rule list. If it doesn't match, I initialize
* the loop with the ->be.
*/
- if (s->current_rule_list == &sess->fe->http_res_rules)
+ if (s->current_rule_list == &sess->fe->http_res_rules ||
+ (sess->fe->defpx && s->current_rule_list == &sess->fe->defpx->http_res_rules))
cur_proxy = sess->fe;
else
cur_proxy = s->be;
+
while (1) {
/* evaluate http-response rules */
if (ret == HTTP_RULE_RES_CONT) {
- ret = http_res_get_intercept_rule(cur_proxy, &cur_proxy->http_res_rules, s);
+ struct list *def_rules, *rules;
+
+ def_rules = ((cur_proxy->defpx && (cur_proxy == s->be || cur_proxy->defpx != s->be->defpx)) ? &cur_proxy->defpx->http_res_rules : NULL);
+ rules = &cur_proxy->http_res_rules;
+
+ ret = http_res_get_intercept_rule(cur_proxy, def_rules, rules, s);
switch (ret) {
case HTTP_RULE_RES_YIELD: /* some data miss, call the function later. */
DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
rep->analysers &= ~an_bit;
rep->analyse_exp = TICK_ETERNITY;
+ s->current_rule = s->current_rule_list = NULL;
return 1;
deny:
rep->analysers &= AN_RES_FLT_END;
s->req.analysers &= AN_REQ_FLT_END;
rep->analyse_exp = TICK_ETERNITY;
+ s->current_rule = s->current_rule_list = NULL;
DBG_TRACE_DEVEL("leaving on error",
STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_HTTP_ERR, s, txn);
return 0;
* and a deny/tarpit rule is matched, it will be filled with this rule's deny
* status.
*/
-static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct list *rules,
- struct stream *s)
+static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct list *def_rules,
+ struct list *rules, struct stream *s)
{
struct session *sess = strm_sess(s);
struct http_txn *txn = s->txn;
if (s->current_rule) {
rule = s->current_rule;
s->current_rule = NULL;
- if (s->current_rule_list == rules)
+ if (s->current_rule_list == rules || (def_rules && s->current_rule_list == def_rules))
goto resume_execution;
}
- s->current_rule_list = rules;
+ s->current_rule_list = ((!def_rules || s->current_rule_list == def_rules) ? rules : def_rules);
+ restart:
/* start the ruleset evaluation in strict mode */
txn->req.flags &= ~HTTP_MSGF_SOFT_RW;
- list_for_each_entry(rule, rules, list) {
+ list_for_each_entry(rule, s->current_rule_list, list) {
/* check optional condition */
if (rule->cond) {
int ret;
}
}
+ if (def_rules && s->current_rule_list == def_rules) {
+ s->current_rule_list = rules;
+ goto restart;
+ }
+
end:
/* if the ruleset evaluation is finished reset the strict mode */
if (rule_ret != HTTP_RULE_RES_YIELD)
* must be returned. If *YIELD is returned, the caller must call again the
* function with the same context.
*/
-static enum rule_result http_res_get_intercept_rule(struct proxy *px, struct list *rules,
- struct stream *s)
+static enum rule_result http_res_get_intercept_rule(struct proxy *px, struct list *def_rules,
+ struct list *rules, struct stream *s)
{
struct session *sess = strm_sess(s);
struct http_txn *txn = s->txn;
if (s->current_rule) {
rule = s->current_rule;
s->current_rule = NULL;
- if (s->current_rule_list == rules)
+ if (s->current_rule_list == rules || (def_rules && s->current_rule_list == def_rules))
goto resume_execution;
}
- s->current_rule_list = rules;
+ s->current_rule_list = ((!def_rules || s->current_rule_list == def_rules) ? rules : def_rules);
+
+ restart:
/* start the ruleset evaluation in strict mode */
txn->rsp.flags &= ~HTTP_MSGF_SOFT_RW;
- list_for_each_entry(rule, rules, list) {
+ list_for_each_entry(rule, s->current_rule_list, list) {
/* check optional condition */
if (rule->cond) {
int ret;
}
}
+ if (def_rules && s->current_rule_list == def_rules) {
+ s->current_rule_list = rules;
+ goto restart;
+ }
+
end:
/* if the ruleset evaluation is finished reset the strict mode */
if (rule_ret != HTTP_RULE_RES_YIELD)
*/
int http_eval_after_res_rules(struct stream *s)
{
+ struct list *def_rules, *rules;
struct session *sess = s->sess;
enum rule_result ret = HTTP_RULE_RES_CONT;
vars_init_head(&s->vars_reqres, SCOPE_RES);
}
- ret = http_res_get_intercept_rule(s->be, &s->be->http_after_res_rules, s);
- if (ret == HTTP_RULE_RES_CONT && sess->fe != s->be)
- ret = http_res_get_intercept_rule(sess->fe, &sess->fe->http_after_res_rules, s);
+
+ def_rules = (s->be->defpx ? &s->be->defpx->http_after_res_rules : NULL);
+ rules = &s->be->http_after_res_rules;
+
+ ret = http_res_get_intercept_rule(s->be, def_rules, rules, s);
+ if (ret == HTTP_RULE_RES_CONT && sess->fe != s->be) {
+ def_rules = ((sess->fe->defpx && sess->fe->defpx != s->be->defpx) ? &sess->fe->defpx->http_after_res_rules : NULL);
+ rules = &sess->fe->http_after_res_rules;
+ ret = http_res_get_intercept_rule(sess->fe, def_rules, rules, s);
+ }
end:
/* All other codes than CONTINUE, STOP or DONE are forbidden */