]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: http-ana: Use a TXN flag to prevent after-response ruleset evaluation
authorChristopher Faulet <cfaulet@haproxy.com>
Fri, 15 May 2020 10:29:46 +0000 (12:29 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 20 May 2020 16:27:13 +0000 (18:27 +0200)
The txn flag TX_CONST_REPLY may now be used to prevent after-response ruleset
evaluation. It is used if this ruleset evaluation failed on an internal error
response. Before, it was done incrementing the parameter <final>. But it is not
really convenient if an intermediary function is used to produce the
response. Using a txn flag could also be a good way to prevent after-response
ruleset evaluation in a different context.

include/types/http_ana.h
src/http_ana.c

index 316a2716d6430ea93ff6df78792ade1574c1a014..1b9891c41921f35c74a33854c77f9e3d637d61f5 100644 (file)
@@ -31,7 +31,8 @@
 /* These are the flags that are found in txn->flags */
 
 /* action flags */
-/* Unusued: 0x00000001..0x00000008 */
+/* Unusued: 0x00000001..0x00000004 */
+#define TX_CONST_REPLY  0x00000008      /* The http reply must not be rewritten (don't eval after-response ruleset) */
 #define TX_CLTARPIT    0x00000010      /* the transaction is tarpitted (anti-dos) */
 
 /* transaction flags dedicated to cookies : bits values 0x20 to 0x80 (0-7 shift 5) */
index 6ff6ada1fde0b867c6fcec5198e877ff58dfe567..e6a43ea132828e69d4b13ff5fa6a776b8705ce76 100644 (file)
@@ -3174,6 +3174,10 @@ int http_eval_after_res_rules(struct stream *s)
        struct session *sess = s->sess;
        enum rule_result ret = HTTP_RULE_RES_CONT;
 
+       /* Eval after-response ruleset only if the reply is not const */
+       if (s->txn->flags & TX_CONST_REPLY)
+               goto end;
+
        /* prune the request variables if not already done and swap to the response variables. */
        if (s->vars_reqres.scope != SCOPE_RES) {
                if (!LIST_ISEMPTY(&s->vars_reqres.head))
@@ -3185,6 +3189,7 @@ int http_eval_after_res_rules(struct stream *s)
        if ((ret == HTTP_RULE_RES_CONT || ret == HTTP_RULE_RES_STOP) && sess->fe != s->be)
                ret = http_res_get_intercept_rule(sess->fe, &sess->fe->http_after_res_rules, s);
 
+  end:
        /* All other codes than CONTINUE, STOP or DONE are forbidden */
        return (ret == HTTP_RULE_RES_CONT || ret == HTTP_RULE_RES_STOP || ret == HTTP_RULE_RES_DONE);
 }
@@ -4591,9 +4596,8 @@ static void http_end_response(struct stream *s)
 /* Forward a response generated by HAProxy (error/redirect/return). This
  * function forwards all pending incoming data. If <final> is set to 0, nothing
  * more is performed. It is used for 1xx informational messages. Otherwise, the
- * transaction is terminated and the request is emptied. if <final> is greater
- * than 1, it means after-response ruleset must not be evaluated. On success 1
- * is returned. If an error occurred, 0 is returned.
+ * transaction is terminated and the request is emptied. On success 1 is
+ * returned. If an error occurred, 0 is returned.
  */
 int http_forward_proxy_resp(struct stream *s, int final)
 {
@@ -4604,7 +4608,8 @@ int http_forward_proxy_resp(struct stream *s, int final)
 
        if (final) {
                htx->flags |= HTX_FL_PROXY_RESP;
-               if (final == 1 && !http_eval_after_res_rules(s))
+
+               if (!http_eval_after_res_rules(s))
                        return 0;
 
                channel_auto_read(req);
@@ -4637,9 +4642,6 @@ void http_server_error(struct stream *s, struct stream_interface *si, int err,
 
 void http_reply_and_close(struct stream *s, short status, const struct buffer *msg)
 {
-       int final = 1;
-
-  retry:
        channel_auto_read(&s->req);
        channel_abort(&s->req);
        channel_auto_close(&s->req);
@@ -4661,17 +4663,17 @@ void http_reply_and_close(struct stream *s, short status, const struct buffer *m
                FLT_STRM_CB(s, flt_http_reply(s, s->txn->status, msg));
                htx = htx_from_buf(&chn->buf);
                if (channel_htx_copy_msg(chn, htx, msg)) {
-                       if (!http_forward_proxy_resp(s, final)) {
+                       if (!http_forward_proxy_resp(s,  1)) {
                                /* On error, return a 500 error message, but
                                 * don't rewrite it if it is already an internal
                                 * error.
                                 */
                                if (s->txn->status == 500)
-                                       final++;
+                                       s->txn->flags |= TX_CONST_REPLY;
                                s->txn->status = 500;
-                               msg = http_error_message(s);
-                               goto retry;
-                       }
+                               s->txn->errmsg = NULL;
+                               return http_reply_and_close(s, s->txn->status, http_error_message(s));
+                       }
                }
        }
 }