BUG/MINOR: http-ana: Don't overwrite outgoing data when an error is reported

When an error is returned to a client, the right message is injected into the
response buffer. It is performed by http_server_error() or
http_replay_and_close(). Both ignore any data already present into the channel's
buffer. While it is legitimate to remove all input data, it is important to not
remove any outgoing data.

So now, we try to append the error message to the response buffer, only removing
input data. We rely on the channel_htx_copy_msg() function to do so. So this
patch depends on the following two commits:

  * MINOR: htx: Add a function to append an HTX message to another one
  * MINOR: htx/channel: Add a function to copy an HTX message in a channel's buffer

This patch must be backported as far as 1.9. However, above patches must be
backported first.
diff --git a/src/http_ana.c b/src/http_ana.c
index 41df061..a276527 100644
--- a/src/http_ana.c
+++ b/src/http_ana.c
@@ -4547,6 +4547,7 @@
 	channel_abort(si_oc(si));
 	channel_auto_close(si_oc(si));
 	channel_htx_erase(si_oc(si), htxbuf(&(si_oc(si))->buf));
+	channel_htx_truncate(si_ic(si), htxbuf(&(si_ic(si))->buf));
 	channel_auto_close(si_ic(si));
 	channel_auto_read(si_ic(si));
 
@@ -4555,14 +4556,16 @@
 	if (msg && !b_is_null(msg)) {
 		struct channel *chn = si_ic(si);
 		struct htx *htx;
+		size_t data;
 
 		FLT_STRM_CB(s, flt_http_reply(s, s->txn->status, msg));
-		chn->buf.data = msg->data;
-		memcpy(chn->buf.area, msg->area, msg->data);
 		htx = htx_from_buf(&chn->buf);
-		htx->flags |= HTX_FL_PROXY_RESP;
-		c_adv(chn, htx->data);
-		chn->total += htx->data;
+		if (channel_htx_copy_msg(chn, htx, msg)) {
+			htx->flags |= HTX_FL_PROXY_RESP;
+			data = htx->data - co_data(chn);
+			c_adv(chn, data);
+			chn->total += data;
+		}
 	}
 	if (!(s->flags & SF_ERR_MASK))
 		s->flags |= err;
@@ -4582,18 +4585,19 @@
 
 	/* <msg> is an HTX structure. So we copy it in the response's
 	 * channel */
-	/* FIXME: It is a problem for now if there is some outgoing data */
 	if (msg && !b_is_null(msg)) {
 		struct channel *chn = &s->res;
 		struct htx *htx;
+		size_t data;
 
 		FLT_STRM_CB(s, flt_http_reply(s, s->txn->status, msg));
-		chn->buf.data = msg->data;
-		memcpy(chn->buf.area, msg->area, msg->data);
 		htx = htx_from_buf(&chn->buf);
-		htx->flags |= HTX_FL_PROXY_RESP;
-		c_adv(chn, htx->data);
-		chn->total += htx->data;
+		if (channel_htx_copy_msg(chn, htx, msg)) {
+			htx->flags |= HTX_FL_PROXY_RESP;
+			data = htx->data - co_data(chn);
+			c_adv(chn, data);
+			chn->total += data;
+		}
 	}
 
 	s->res.wex = tick_add_ifset(now_ms, s->res.wto);