]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: http-ana: Throw a 500 error if after-response ruleset fails on errors
authorChristopher Faulet <cfaulet@haproxy.com>
Mon, 20 Apr 2020 12:58:38 +0000 (14:58 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Mon, 27 Apr 2020 05:20:44 +0000 (07:20 +0200)
It is the intended behaviour. But because of a bug, the 500 error resulting of a
rewrite failure during http-after-response ruleset evaluation is also
rewritten. So if at this step, if there is also a rewrite error, the session is
closed and no error message is returned.

Instead, we must be sure to not evaluate the http-after-response rules on an
error message if it is was thrown because of a rewrite failure on a previous
error message.

It is a 2.2-dev2+ bug. No need to backport. This patch should fix the issue

src/http_ana.c

index e0fe67e248e8ebcd1e0e9e0e03ef36e38cd56941..d475cd24deeb296996ea7402555eeac51664b4cb 100644 (file)
@@ -4557,8 +4557,9 @@ 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. On success 1 is
- * returned. If an error occurred, 0 is returned.
+ * 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.
  */
 int http_forward_proxy_resp(struct stream *s, int final)
 {
@@ -4569,7 +4570,7 @@ int http_forward_proxy_resp(struct stream *s, int final)
 
        if (final) {
                htx->flags |= HTX_FL_PROXY_RESP;
-               if (!http_eval_after_res_rules(s))
+               if (final == 1 && !http_eval_after_res_rules(s))
                        return 0;
 
                channel_auto_read(req);
@@ -4602,6 +4603,9 @@ 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);
@@ -4623,9 +4627,16 @@ 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, 1) && s->txn->status != 500) {
+                       if (!http_forward_proxy_resp(s, final)) {
+                               /* 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->status = 500;
-                               http_reply_and_close(s, s->txn->status, http_error_message(s));
+                               msg = http_error_message(s);
+                               goto retry;
                        }
                }
        }