BUG/MINOR: http_fetch/htx: Allow permissive sample prefetch for the HTX

As for smp_prefetch_http(), there is now a way to successfully perform a
prefetch in HTX, even if the message forwarding already begun. It is used for
the sample fetches "req.proto_http" and "method".

This patch must be backported to 1.9.
diff --git a/include/proto/http_fetch.h b/include/proto/http_fetch.h
index e7623b4..88f15fb 100644
--- a/include/proto/http_fetch.h
+++ b/include/proto/http_fetch.h
@@ -40,7 +40,7 @@
                   struct channel *chn, struct sample *smp, int req_vol);
 
 struct htx;
-struct htx *smp_prefetch_htx(struct sample *smp, struct channel *chn);
+struct htx *smp_prefetch_htx(struct sample *smp, struct channel *chn, int vol);
 
 int val_hdr(struct arg *arg, char **err_msg);
 
diff --git a/src/http_fetch.c b/src/http_fetch.c
index 599773a..2d639f2 100644
--- a/src/http_fetch.c
+++ b/src/http_fetch.c
@@ -160,7 +160,8 @@
 /* This function ensures that the prerequisites for an L7 fetch are ready,
  * which means that a request or response is ready. If some data is missing,
  * a parsing attempt is made. This is useful in TCP-based ACLs which are able
- * to extract data from L7.
+ * to extract data from L7. If <vol> is non-null during a prefetch, another
+ * test is made to ensure the required information is not gone.
  *
  * The function returns :
  *   NULL with SMP_F_MAY_CHANGE in the sample flags if some data is missing to
@@ -169,7 +170,7 @@
  *     we'll never have any HTTP message there ;
  *   The HTX message if ready
  */
-struct htx *smp_prefetch_htx(struct sample *smp, struct channel *chn)
+struct htx *smp_prefetch_htx(struct sample *smp, struct channel *chn, int vol)
 {
 	struct stream *s = smp->strm;
 	struct http_txn *txn = NULL;
@@ -209,7 +210,7 @@
 			}
 		}
 		sl = http_find_stline(htx);
-		if (!sl) {
+		if (vol && !sl) {
 			/* The start-line was already forwarded, it is too late to fetch anything */
 			return NULL;
 		}
@@ -416,7 +417,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 0);
 
 		if (!htx)
 			return 0;
@@ -470,7 +471,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 		struct htx_sl *sl;
 
 		if (!htx)
@@ -510,7 +511,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 		struct htx_sl *sl;
 
 		if (!htx)
@@ -551,7 +552,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 		struct htx_sl *sl;
 
 		if (!htx)
@@ -606,7 +607,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 		struct buffer *temp;
 		int32_t pos;
 
@@ -674,7 +675,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 		struct buffer *temp;
 		char *p, *end;
 		int32_t pos;
@@ -835,7 +836,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 		int32_t pos;
 
 		if (!htx)
@@ -906,7 +907,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 		int32_t pos;
 		unsigned long long len = 0;
 
@@ -954,7 +955,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 		int32_t pos;
 		unsigned long long len = 0;
 
@@ -1002,7 +1003,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 		struct htx_sl *sl;
 
 		if (!htx)
@@ -1034,7 +1035,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 		struct htx_sl *sl;
 
 		if (!htx)
@@ -1067,7 +1068,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 		struct htx_sl *sl;
 
 		if (!htx)
@@ -1106,7 +1107,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 		struct http_hdr_ctx *ctx = smp->ctx.a[0];
 		struct ist name;
 
@@ -1210,7 +1211,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 		struct http_hdr_ctx ctx;
 		struct ist name;
 
@@ -1269,7 +1270,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 		int32_t pos;
 
 		if (!htx)
@@ -1340,7 +1341,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 		struct http_hdr_ctx *ctx = smp->ctx.a[0];
 		struct ist name;
 
@@ -1444,7 +1445,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 		struct http_hdr_ctx ctx;
 		struct ist name;
 
@@ -1553,7 +1554,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 		struct htx_sl *sl;
 		struct ist path;
 		size_t len;
@@ -1614,7 +1615,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 		struct htx_sl *sl;
 		struct http_hdr_ctx ctx;
 		struct ist path;
@@ -1700,7 +1701,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 		struct htx_sl *sl;
 		struct http_hdr_ctx ctx;
 		struct ist path;
@@ -1826,7 +1827,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 		struct htx_sl *sl;
 
 		if (!htx)
@@ -1866,7 +1867,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 0);
 
 		if (!htx)
 			return 0;
@@ -1902,7 +1903,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 
 		if (!htx)
 			return 0;
@@ -1930,7 +1931,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 
 		if (!htx)
 			return 0;
@@ -2138,7 +2139,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 		struct http_hdr_ctx *ctx = smp->ctx.a[2];
 		struct ist hdr;
 
@@ -2304,7 +2305,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 		struct http_hdr_ctx ctx;
 		struct ist hdr;
 
@@ -2495,7 +2496,7 @@
 	if (!smp->ctx.a[0]) { // first call, find the query string
 		if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 			/* HTX version */
-			struct htx *htx = smp_prefetch_htx(smp, chn);
+			struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 			struct htx_sl *sl;
 
 			if (!htx)
@@ -2560,7 +2561,7 @@
 	if (!smp->ctx.a[0]) { // first call, find the query string
 		if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 			/* HTX version */
-			struct htx *htx = smp_prefetch_htx(smp, chn);
+			struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 			struct buffer *temp;
 			int32_t pos;
 
@@ -2663,7 +2664,7 @@
 
 	if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
 		/* HTX version */
-		struct htx *htx = smp_prefetch_htx(smp, chn);
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
 		struct http_hdr_ctx ctx;
 		struct htx_sl *sl;
 		struct ist path;