[master] 18f63d489 Add "error" state to backend fetch and response

Poul-Henning Kamp phk at FreeBSD.org
Mon Jun 17 07:00:17 UTC 2019


commit 18f63d489704db53d6b3f25ab13858f1762c37fd
Author: Andrew Wiik <andrew at varnish-software.com>
Date:   Tue Jun 4 11:01:04 2019 -0400

    Add "error" state to backend fetch and response

diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index a6ade1d39..a204200c1 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -412,6 +412,9 @@ struct busyobj {
 
 	struct http_conn	*htc;
 
+	uint16_t		err_code;
+	const char		*err_reason;
+
 	struct pool_task	fetch_task;
 
 #define BO_FLAG(l, r, w, d) unsigned	l:1;
diff --git a/bin/varnishd/cache/cache_fetch.c b/bin/varnishd/cache/cache_fetch.c
index 88ee91cd8..c01de9387 100644
--- a/bin/varnishd/cache/cache_fetch.c
+++ b/bin/varnishd/cache/cache_fetch.c
@@ -277,7 +277,7 @@ vbf_stp_startfetch(struct worker *wrk, struct busyobj *bo)
 	if (wrk->handling == VCL_RET_ABANDON || wrk->handling == VCL_RET_FAIL)
 		return (F_STP_FAIL);
 
-	assert (wrk->handling == VCL_RET_FETCH);
+	assert (wrk->handling == VCL_RET_FETCH || wrk->handling == VCL_RET_ERROR);
 
 	HTTP_Setup(bo->beresp, bo->ws, bo->vsl, SLT_BerespMethod);
 
@@ -290,6 +290,9 @@ vbf_stp_startfetch(struct worker *wrk, struct busyobj *bo)
 	bo->vfc->resp = bo->beresp;
 	bo->vfc->req = bo->bereq;
 
+	if (wrk->handling == VCL_RET_ERROR)
+		return (F_STP_ERROR);
+
 	i = VDI_GetHdr(bo);
 
 	now = W_TIM_real(wrk);
@@ -384,10 +387,14 @@ vbf_stp_startfetch(struct worker *wrk, struct busyobj *bo)
 
 	VCL_backend_response_method(bo->vcl, wrk, NULL, bo, NULL);
 
-	if (wrk->handling == VCL_RET_ABANDON || wrk->handling == VCL_RET_FAIL) {
+	if (wrk->handling == VCL_RET_ABANDON || wrk->handling == VCL_RET_FAIL ||
+	    wrk->handling == VCL_RET_ERROR) {
 		bo->htc->doclose = SC_RESP_CLOSE;
 		VDI_Finish(bo);
-		return (F_STP_FAIL);
+		if (wrk->handling == VCL_RET_ERROR)
+			return (F_STP_ERROR);
+		else
+			return (F_STP_FAIL);
 	}
 
 	if (wrk->handling == VCL_RET_RETRY) {
@@ -705,7 +712,8 @@ vbf_stp_error(struct worker *wrk, struct busyobj *bo)
 	AN(bo->fetch_objcore->flags & OC_F_BUSY);
 	assert(bo->director_state == DIR_S_NULL);
 
-	wrk->stats->fetch_failed++;
+	if (wrk->handling !=  VCL_RET_ERROR)
+		wrk->stats->fetch_failed++;
 
 	now = W_TIM_real(wrk);
 	VSLb_ts_busyobj(bo, "Error", now);
@@ -719,7 +727,11 @@ vbf_stp_error(struct worker *wrk, struct busyobj *bo)
 	// XXX: reset all beresp flags ?
 
 	HTTP_Setup(bo->beresp, bo->ws, bo->vsl, SLT_BerespMethod);
-	http_PutResponse(bo->beresp, "HTTP/1.1", 503, "Backend fetch failed");
+	if (bo->err_code > 0)
+		http_PutResponse(bo->beresp, "HTTP/1.1", bo->err_code, bo->err_reason);
+	else
+		http_PutResponse(bo->beresp, "HTTP/1.1", 503, "Backend fetch failed");
+
 	http_TimeHeader(bo->beresp, "Date: ", now);
 	http_SetHeader(bo->beresp, "Server: Varnish");
 
diff --git a/bin/varnishd/cache/cache_vrt.c b/bin/varnishd/cache/cache_vrt.c
index 854a690f2..81cc12b09 100644
--- a/bin/varnishd/cache/cache_vrt.c
+++ b/bin/varnishd/cache/cache_vrt.c
@@ -55,9 +55,18 @@ VRT_synth(VRT_CTX, VCL_INT code, VCL_STRING reason)
 {
 
 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
-	CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
+	assert(ctx->req != NULL || ctx->bo != NULL);
 	if (code < 100 || code > 65535)
 		code = 503;
+
+	if (ctx->req == NULL) {
+		CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
+		ctx->bo->err_code = (uint16_t)code;
+		ctx->bo->err_reason = reason ? reason
+		    : http_Status2Reason(ctx->bo->err_code % 1000, NULL);
+		return;
+	}
+
 	ctx->req->err_code = (uint16_t)code;
 	ctx->req->err_reason = reason ? reason
 	    : http_Status2Reason(ctx->req->err_code % 1000, NULL);
diff --git a/bin/varnishtest/tests/v00062.vtc b/bin/varnishtest/tests/v00062.vtc
new file mode 100644
index 000000000..365b949d6
--- /dev/null
+++ b/bin/varnishtest/tests/v00062.vtc
@@ -0,0 +1,78 @@
+varnishtest "backend_(fetch|response) error state with custom status/reason"
+
+server s1 -repeat 3 {
+	rxreq
+	txresp
+} -start
+
+varnish v1 -vcl+backend {
+	sub vcl_backend_fetch {
+		if (bereq.url == "/errorsynth") {
+			return (error(403));
+		}
+
+		if (bereq.url == "/errorsynthbody") {
+			return (error(403, "Steven has no cookies"));
+		}
+
+		if (bereq.url == "/error") {
+			return (error);
+		}
+	}
+
+	sub vcl_backend_response {
+		if (bereq.url == "/resperrorsynth") {
+			return (error(403));
+		}
+
+		if (bereq.url == "/resperrorsynthbody") {
+			return (error(403, "Steven has no cookies"));
+		}
+
+		if (bereq.url == "/resperror") {
+			return (error);
+		}
+	}
+
+	sub vcl_backend_error {
+		set beresp.http.error = "visited";
+	}
+} -start
+
+client c1 {
+	txreq -url /error
+	rxresp
+	expect resp.status == 503
+	expect resp.http.error == visited
+
+	txreq -url /errorsynth
+	rxresp
+	expect resp.status == 403
+	expect resp.http.error == visited
+
+	txreq -url /errorsynthbody
+	rxresp
+	expect resp.status == 403
+	expect resp.reason == "Steven has no cookies"
+	expect resp.http.error == visited
+
+	txreq -url /resperror
+	rxresp
+	expect resp.status == 503
+	expect resp.http.error == visited
+
+	txreq -url /resperrorsynth
+	rxresp
+	expect resp.status == 403
+	expect resp.http.error == visited
+
+	txreq -url /resperrorsynthbody
+	rxresp
+	expect resp.status == 403
+	expect resp.reason == "Steven has no cookies"
+	expect resp.http.error == visited
+} -run
+
+# Make sure we don't increment the failed fetch counter
+
+varnish v1 -expect fetch_failed == 0
diff --git a/doc/graphviz/cache_fetch.dot b/doc/graphviz/cache_fetch.dot
index eb68f72a3..96c0967a0 100644
--- a/doc/graphviz/cache_fetch.dot
+++ b/doc/graphviz/cache_fetch.dot
@@ -39,16 +39,18 @@ digraph cache_fetch {
 		/* vbf_stp_startfetch() */
 		v_b_f [
 			    shape=record
-			    label="{vbf_stp_startfetch:|{vcl_backend_fetch\{\}|bereq.*}|{fail|abandon|<fetch>fetch}}"
+			    label="{vbf_stp_startfetch:|{vcl_backend_fetch\{\}|bereq.*}|{<error>error|fail|abandon|<fetch>fetch}}"
 		]
+		v_b_f:error:s -> v_b_e
 		v_b_f:fetch:s -> v_b_hdrs [style=bold]
 		v_b_hdrs [ label="send bereq,\nread beresp (headers)"]
 		v_b_hdrs -> v_b_r [style=bold]
 		v_b_hdrs -> v_b_e
 		v_b_r [
 			    shape=record
-			    label="{vbf_stp_startfetch:|{vcl_backend_response\{\}|{bereq.*|beresp.*}}|{fail|{retry|{<max>max?|<retry>ok?}}|abandon|{deliver or pass|{<fetch_304>304?|<non_304>other?}}}}"
+			    label="{vbf_stp_startfetch:|{vcl_backend_response\{\}|{bereq.*|beresp.*}}|{<error>error|fail|{retry|{<max>max?|<retry>ok?}}|abandon|{deliver or pass|{<fetch_304>304?|<non_304>other?}}}}"
 		]
+		v_b_r:error:s -> v_b_e
 		v_b_r:retry -> v_b_r_retry [color=purple]
 		v_b_r:max -> v_b_e
 		v_b_r:fetch_304:s -> vbf_stp_condfetch
@@ -90,8 +92,8 @@ digraph cache_fetch {
 		]
 		vbf_stp_condfetch:ok:s -> vbf_stp_fetchend
 
-		error [shape=plaintext]
-		error -> FETCH_FAIL
+		fail [shape=plaintext]
+		fail -> FETCH_FAIL
 
 		/* vbf_stp_error */
 		v_b_e [
diff --git a/doc/graphviz/cache_fetch.svg b/doc/graphviz/cache_fetch.svg
index aeb38a95b..fa09e056e 100644
--- a/doc/graphviz/cache_fetch.svg
+++ b/doc/graphviz/cache_fetch.svg
@@ -1,283 +1,338 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<!-- Generated by graphviz version 2.38.0 (20140413.2041)
+<!-- Generated by graphviz version 2.40.1 (20161225.0304)
  -->
 <!-- Title: cache_fetch Pages: 1 -->
-<svg width="720pt" height="1052pt"
- viewBox="36.00 36.00 684.00 1015.74" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(40 1011.74)">
+<svg width="700pt" height="1318pt"
+ viewBox="36.00 36.00 664.00 1281.74" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(40 1277.7401)">
 <title>cache_fetch</title>
-<polygon fill="white" stroke="none" points="-4,4 -4,-975.74 644,-975.74 644,4 -4,4"/>
-<g id="clust1" class="cluster"><title>cluster_backend</title>
-<polygon fill="aliceblue" stroke="aliceblue" points="8,-8 8,-963.74 632,-963.74 632,-8 8,-8"/>
+<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-1241.7401 624,-1241.7401 624,4 -4,4"/>
+<g id="clust1" class="cluster">
+<title>cluster_backend</title>
+<polygon fill="#f0f8ff" stroke="#f0f8ff" points="8,-8 8,-1229.7401 612,-1229.7401 612,-8 8,-8"/>
 </g>
 <!-- RETRY -->
-<g id="node1" class="node"><title>RETRY</title>
-<text text-anchor="middle" x="396" y="-942.04" font-family="Times,serif" font-size="14.00">RETRY</text>
+<g id="node1" class="node">
+<title>RETRY</title>
+<text text-anchor="middle" x="433" y="-1208.0401" font-family="Times,serif" font-size="14.00" fill="#000000">RETRY</text>
 </g>
 <!-- v_b_f -->
-<g id="node4" class="node"><title>v_b_f</title>
-<polygon fill="none" stroke="black" points="160.5,-821.24 160.5,-890.24 357.5,-890.24 357.5,-821.24 160.5,-821.24"/>
-<text text-anchor="middle" x="259" y="-875.04" font-family="Times,serif" font-size="14.00">vbf_stp_startfetch:</text>
-<polyline fill="none" stroke="black" points="160.5,-867.24 357.5,-867.24 "/>
-<text text-anchor="middle" x="229.5" y="-852.04" font-family="Times,serif" font-size="14.00">vcl_backend_fetch{}</text>
-<polyline fill="none" stroke="black" points="298.5,-844.24 298.5,-867.24 "/>
-<text text-anchor="middle" x="328" y="-852.04" font-family="Times,serif" font-size="14.00">bereq.*</text>
-<polyline fill="none" stroke="black" points="160.5,-844.24 357.5,-844.24 "/>
-<text text-anchor="middle" x="186.5" y="-829.04" font-family="Times,serif" font-size="14.00">fail</text>
-<polyline fill="none" stroke="black" points="212.5,-821.24 212.5,-844.24 "/>
-<text text-anchor="middle" x="254" y="-829.04" font-family="Times,serif" font-size="14.00">abandon</text>
-<polyline fill="none" stroke="black" points="295.5,-821.24 295.5,-844.24 "/>
-<text text-anchor="middle" x="326.5" y="-829.04" font-family="Times,serif" font-size="14.00">fetch</text>
+<g id="node4" class="node">
+<title>v_b_f</title>
+<polygon fill="none" stroke="#000000" points="207.5,-1049.2401 207.5,-1118.2401 396.5,-1118.2401 396.5,-1049.2401 207.5,-1049.2401"/>
+<text text-anchor="middle" x="302" y="-1103.0401" font-family="Times,serif" font-size="14.00" fill="#000000">vbf_stp_startfetch:</text>
+<polyline fill="none" stroke="#000000" points="207.5,-1095.2401 396.5,-1095.2401 "/>
+<text text-anchor="middle" x="273.5" y="-1080.0401" font-family="Times,serif" font-size="14.00" fill="#000000">vcl_backend_fetch{}</text>
+<polyline fill="none" stroke="#000000" points="339.5,-1072.2401 339.5,-1095.2401 "/>
+<text text-anchor="middle" x="368" y="-1080.0401" font-family="Times,serif" font-size="14.00" fill="#000000">bereq.*</text>
+<polyline fill="none" stroke="#000000" points="207.5,-1072.2401 396.5,-1072.2401 "/>
+<text text-anchor="middle" x="229.5" y="-1057.0401" font-family="Times,serif" font-size="14.00" fill="#000000">error</text>
+<polyline fill="none" stroke="#000000" points="251.5,-1049.2401 251.5,-1072.2401 "/>
+<text text-anchor="middle" x="269.5" y="-1057.0401" font-family="Times,serif" font-size="14.00" fill="#000000">fail</text>
+<polyline fill="none" stroke="#000000" points="287.5,-1049.2401 287.5,-1072.2401 "/>
+<text text-anchor="middle" x="319" y="-1057.0401" font-family="Times,serif" font-size="14.00" fill="#000000">abandon</text>
+<polyline fill="none" stroke="#000000" points="350.5,-1049.2401 350.5,-1072.2401 "/>
+<text text-anchor="middle" x="373.5" y="-1057.0401" font-family="Times,serif" font-size="14.00" fill="#000000">fetch</text>
 </g>
 <!-- RETRY->v_b_f -->
-<g id="edge4" class="edge"><title>RETRY->v_b_f</title>
-<path fill="none" stroke="purple" d="M369.26,-927.564C355.073,-918.451 337.021,-906.856 319.652,-895.699"/>
-<polygon fill="purple" stroke="purple" points="321.505,-892.73 311.2,-890.27 317.722,-898.619 321.505,-892.73"/>
+<g id="edge4" class="edge">
+<title>RETRY->v_b_f</title>
+<path fill="none" stroke="#a020f0" d="M414.5087,-1193.6723C396.4206,-1175.9984 368.2234,-1148.447 344.5834,-1125.3483"/>
+<polygon fill="#a020f0" stroke="#a020f0" points="347.0079,-1122.8239 337.4093,-1118.3386 342.1158,-1127.8307 347.0079,-1122.8239"/>
 </g>
 <!-- v_b_f_BGFETCH -->
-<g id="node2" class="node"><title>v_b_f_BGFETCH</title>
-<polygon fill="turquoise" stroke="turquoise" points="345.5,-963.74 262.5,-963.74 262.5,-927.74 345.5,-927.74 345.5,-963.74"/>
-<text text-anchor="middle" x="304" y="-942.04" font-family="Times,serif" font-size="14.00">BGFETCH</text>
+<g id="node2" class="node">
+<title>v_b_f_BGFETCH</title>
+<polygon fill="#40e0d0" stroke="#40e0d0" points="384,-1229.7401 306,-1229.7401 306,-1193.7401 384,-1193.7401 384,-1229.7401"/>
+<text text-anchor="middle" x="345" y="-1208.0401" font-family="Times,serif" font-size="14.00" fill="#000000">BGFETCH</text>
 </g>
 <!-- v_b_f_BGFETCH->v_b_f -->
-<g id="edge1" class="edge"><title>v_b_f_BGFETCH->v_b_f</title>
-<path fill="none" stroke="green" stroke-width="2" d="M295.109,-927.354C290.991,-919.301 285.899,-909.342 280.85,-899.468"/>
-<polygon fill="green" stroke="green" stroke-width="2" points="283.924,-897.792 276.254,-890.482 277.691,-900.979 283.924,-897.792"/>
+<g id="edge1" class="edge">
+<title>v_b_f_BGFETCH->v_b_f</title>
+<path fill="none" stroke="#00ff00" stroke-width="2" d="M338.9304,-1193.6723C333.2233,-1176.684 324.4506,-1150.5697 316.8873,-1128.0558"/>
+<polygon fill="#00ff00" stroke="#00ff00" stroke-width="2" points="320.1253,-1126.7034 313.6229,-1118.3386 313.4897,-1128.9326 320.1253,-1126.7034"/>
 </g>
 <!-- v_b_f_FETCH -->
-<g id="node3" class="node"><title>v_b_f_FETCH</title>
-<polygon fill="turquoise" stroke="turquoise" points="244.5,-963.74 181.5,-963.74 181.5,-927.74 244.5,-927.74 244.5,-963.74"/>
-<text text-anchor="middle" x="213" y="-942.04" font-family="Times,serif" font-size="14.00">FETCH</text>
+<g id="node3" class="node">
+<title>v_b_f_FETCH</title>
+<polygon fill="#40e0d0" stroke="#40e0d0" points="287.5,-1229.7401 228.5,-1229.7401 228.5,-1193.7401 287.5,-1193.7401 287.5,-1229.7401"/>
+<text text-anchor="middle" x="258" y="-1208.0401" font-family="Times,serif" font-size="14.00" fill="#000000">FETCH</text>
 </g>
 <!-- v_b_f_FETCH->v_b_f -->
-<g id="edge2" class="edge"><title>v_b_f_FETCH->v_b_f</title>
-<path fill="none" stroke="blue" stroke-width="2" d="M216.584,-927.354C219.926,-919.301 224.717,-909.342 229.917,-899.468"/>
-<polygon fill="blue" stroke="blue" stroke-width="2" points="233.099,-900.943 234.778,-890.482 226.942,-897.613 233.099,-900.943"/>
+<g id="edge2" class="edge">
+<title>v_b_f_FETCH->v_b_f</title>
+<path fill="none" stroke="#0000ff" stroke-width="2" d="M259.3379,-1193.6723C263.4509,-1176.6078 271.9569,-1150.3353 280.422,-1127.7531"/>
+<polygon fill="#0000ff" stroke="#0000ff" stroke-width="2" points="283.7197,-1128.9287 284.0345,-1118.3386 277.1843,-1126.421 283.7197,-1128.9287"/>
 </g>
 <!-- v_b_f_FETCH->v_b_f -->
-<g id="edge3" class="edge"><title>v_b_f_FETCH->v_b_f</title>
-<path fill="none" stroke="red" stroke-width="2" d="M227.592,-927.354C232.67,-919.301 238.29,-909.342 243.412,-899.468"/>
-<polygon fill="red" stroke="red" stroke-width="2" points="246.566,-900.987 247.946,-890.482 240.317,-897.833 246.566,-900.987"/>
+<g id="edge3" class="edge">
+<title>v_b_f_FETCH->v_b_f</title>
+<path fill="none" stroke="#ff0000" stroke-width="2" d="M269.0837,-1193.6723C276.6685,-1176.684 286.1736,-1150.5697 293.2243,-1128.0558"/>
+<polygon fill="#ff0000" stroke="#ff0000" stroke-width="2" points="296.6184,-1128.9243 296.179,-1118.3386 289.9212,-1126.8878 296.6184,-1128.9243"/>
+</g>
+<!-- v_b_e -->
+<g id="node5" class="node">
+<title>v_b_e</title>
+<polygon fill="none" stroke="#000000" points="160,-538.5 160,-653.5 394,-653.5 394,-538.5 160,-538.5"/>
+<text text-anchor="middle" x="277" y="-638.3" font-family="Times,serif" font-size="14.00" fill="#000000">vbf_stp_error:</text>
+<polyline fill="none" stroke="#000000" points="160,-630.5 394,-630.5 "/>
+<text text-anchor="middle" x="235.5" y="-603.8" font-family="Times,serif" font-size="14.00" fill="#000000">vcl_backend_error{}</text>
+<polyline fill="none" stroke="#000000" points="311,-584.5 311,-630.5 "/>
+<text text-anchor="middle" x="352.5" y="-615.3" font-family="Times,serif" font-size="14.00" fill="#000000">bereq.*</text>
+<polyline fill="none" stroke="#000000" points="311,-607.5 394,-607.5 "/>
+<text text-anchor="middle" x="352.5" y="-592.3" font-family="Times,serif" font-size="14.00" fill="#000000">beresp.*</text>
+<polyline fill="none" stroke="#000000" points="160,-584.5 394,-584.5 "/>
+<text text-anchor="middle" x="219" y="-569.3" font-family="Times,serif" font-size="14.00" fill="#000000">retry</text>
+<polyline fill="none" stroke="#000000" points="160,-561.5 278,-561.5 "/>
+<text text-anchor="middle" x="177.5" y="-546.3" font-family="Times,serif" font-size="14.00" fill="#000000">fail</text>
+<polyline fill="none" stroke="#000000" points="195,-538.5 195,-561.5 "/>
+<text text-anchor="middle" x="218.5" y="-546.3" font-family="Times,serif" font-size="14.00" fill="#000000">max?</text>
+<polyline fill="none" stroke="#000000" points="242,-538.5 242,-561.5 "/>
+<text text-anchor="middle" x="260" y="-546.3" font-family="Times,serif" font-size="14.00" fill="#000000">ok?</text>
+<polyline fill="none" stroke="#000000" points="278,-538.5 278,-584.5 "/>
+<text text-anchor="middle" x="309" y="-557.8" font-family="Times,serif" font-size="14.00" fill="#000000">abandon</text>
+<polyline fill="none" stroke="#000000" points="340,-538.5 340,-584.5 "/>
+<text text-anchor="middle" x="367" y="-557.8" font-family="Times,serif" font-size="14.00" fill="#000000">deliver</text>
+</g>
+<!-- v_b_f->v_b_e -->
+<g id="edge5" class="edge">
+<title>v_b_f:s->v_b_e</title>
+<path fill="none" stroke="#000000" d="M229,-1048.7401C229,-1032.0734 229,-1027.9068 229,-1011.2401 229,-1011.2401 229,-1011.2401 229,-691.5 229,-681.9283 230.9488,-672.3366 234.061,-663.1216"/>
+<polygon fill="#000000" stroke="#000000" points="237.3724,-664.2616 237.6924,-653.6716 230.8382,-661.7506 237.3724,-664.2616"/>
 </g>
 <!-- v_b_hdrs -->
-<g id="node5" class="node"><title>v_b_hdrs</title>
-<ellipse fill="none" stroke="black" cx="327" cy="-756.87" rx="96.7474" ry="26.7407"/>
-<text text-anchor="middle" x="327" y="-760.67" font-family="Times,serif" font-size="14.00">send bereq,</text>
-<text text-anchor="middle" x="327" y="-745.67" font-family="Times,serif" font-size="14.00">read beresp (headers)</text>
+<g id="node6" class="node">
+<title>v_b_hdrs</title>
+<ellipse fill="none" stroke="#000000" cx="374" cy="-946.8701" rx="94.0904" ry="26.7407"/>
+<text text-anchor="middle" x="374" y="-950.6701" font-family="Times,serif" font-size="14.00" fill="#000000">send bereq,</text>
+<text text-anchor="middle" x="374" y="-935.6701" font-family="Times,serif" font-size="14.00" fill="#000000">read beresp (headers)</text>
 </g>
 <!-- v_b_f->v_b_hdrs -->
-<g id="edge5" class="edge"><title>v_b_f:fetch:s->v_b_hdrs</title>
-<path fill="none" stroke="black" stroke-width="2" d="M327,-820.74C327,-812.127 327,-802.849 327,-794.136"/>
-<polygon fill="black" stroke="black" stroke-width="2" points="330.5,-793.87 327,-783.87 323.5,-793.87 330.5,-793.87"/>
+<g id="edge6" class="edge">
+<title>v_b_f:s->v_b_hdrs</title>
+<path fill="none" stroke="#000000" stroke-width="2" d="M374,-1048.7401C374,-1027.4011 374,-1003.5478 374,-984.2904"/>
+<polygon fill="#000000" stroke="#000000" stroke-width="2" points="377.5001,-984.1098 374,-974.1098 370.5001,-984.1098 377.5001,-984.1098"/>
 </g>
-<!-- v_b_r -->
-<g id="node6" class="node"><title>v_b_r</title>
-<polygon fill="none" stroke="black" points="304.5,-577.5 304.5,-692.5 589.5,-692.5 589.5,-577.5 304.5,-577.5"/>
-<text text-anchor="middle" x="447" y="-677.3" font-family="Times,serif" font-size="14.00">vbf_stp_startfetch:</text>
-<polyline fill="none" stroke="black" points="304.5,-669.5 589.5,-669.5 "/>
-<text text-anchor="middle" x="399.5" y="-642.8" font-family="Times,serif" font-size="14.00">vcl_backend_response{}</text>
-<polyline fill="none" stroke="black" points="494.5,-623.5 494.5,-669.5 "/>
-<text text-anchor="middle" x="542" y="-654.3" font-family="Times,serif" font-size="14.00">bereq.*</text>
-<polyline fill="none" stroke="black" points="494.5,-646.5 589.5,-646.5 "/>
-<text text-anchor="middle" x="542" y="-631.3" font-family="Times,serif" font-size="14.00">beresp.*</text>
-<polyline fill="none" stroke="black" points="304.5,-623.5 589.5,-623.5 "/>
-<text text-anchor="middle" x="322" y="-596.8" font-family="Times,serif" font-size="14.00">fail</text>
-<polyline fill="none" stroke="black" points="339.5,-577.5 339.5,-623.5 "/>
-<text text-anchor="middle" x="382" y="-608.3" font-family="Times,serif" font-size="14.00">retry</text>
-<polyline fill="none" stroke="black" points="339.5,-600.5 424.5,-600.5 "/>
-<text text-anchor="middle" x="363" y="-585.3" font-family="Times,serif" font-size="14.00">max?</text>
-<polyline fill="none" stroke="black" points="386.5,-577.5 386.5,-600.5 "/>
-<text text-anchor="middle" x="405.5" y="-585.3" font-family="Times,serif" font-size="14.00">ok?</text>
-<polyline fill="none" stroke="black" points="424.5,-577.5 424.5,-623.5 "/>
-<text text-anchor="middle" x="457.5" y="-596.8" font-family="Times,serif" font-size="14.00">abandon</text>
-<polyline fill="none" stroke="black" points="490.5,-577.5 490.5,-623.5 "/>
-<text text-anchor="middle" x="540" y="-608.3" font-family="Times,serif" font-size="14.00">deliver or pass</text>
-<polyline fill="none" stroke="black" points="490.5,-600.5 589.5,-600.5 "/>
-<text text-anchor="middle" x="513.5" y="-585.3" font-family="Times,serif" font-size="14.00">304?</text>
-<polyline fill="none" stroke="black" points="536.5,-577.5 536.5,-600.5 "/>
-<text text-anchor="middle" x="563" y="-585.3" font-family="Times,serif" font-size="14.00">other?</text>
+<!-- FETCH_DONE -->
+<g id="node13" class="node">
+<title>FETCH_DONE</title>
+<polygon fill="#40e0d0" stroke="#40e0d0" points="410,-44 306,-44 306,-8 410,-8 410,-44"/>
+<text text-anchor="middle" x="358" y="-22.3" font-family="Times,serif" font-size="14.00" fill="#000000">FETCH_DONE</text>
 </g>
-<!-- v_b_hdrs->v_b_r -->
-<g id="edge6" class="edge"><title>v_b_hdrs->v_b_r</title>
-<path fill="none" stroke="black" stroke-width="2" d="M352.156,-730.741C361.289,-721.618 372.07,-710.848 383.029,-699.901"/>
-<polygon fill="black" stroke="black" stroke-width="2" points="385.64,-702.241 390.241,-692.698 380.692,-697.289 385.64,-702.241"/>
+<!-- v_b_e->FETCH_DONE -->
+<g id="edge20" class="edge">
+<title>v_b_e:deliver->FETCH_DONE</title>
+<path fill="none" stroke="#000000" d="M367,-538C367,-474.7525 308,-471.7475 308,-408.5 308,-408.5 308,-408.5 308,-81.5 308,-69.8644 314.1412,-59.5678 322.1192,-51.1007"/>
+<polygon fill="#000000" stroke="#000000" points="324.6221,-53.5511 329.4947,-44.1432 319.8188,-48.4592 324.6221,-53.5511"/>
+<text text-anchor="middle" x="353.5" y="-229.8" font-family="Times,serif" font-size="14.00" fill="#000000">"backend synth"</text>
 </g>
-<!-- v_b_e -->
-<g id="node7" class="node"><title>v_b_e</title>
-<polygon fill="none" stroke="black" points="164,-424.5 164,-539.5 406,-539.5 406,-424.5 164,-424.5"/>
-<text text-anchor="middle" x="285" y="-524.3" font-family="Times,serif" font-size="14.00">vbf_stp_error:</text>
-<polyline fill="none" stroke="black" points="164,-516.5 406,-516.5 "/>
-<text text-anchor="middle" x="242.5" y="-489.8" font-family="Times,serif" font-size="14.00">vcl_backend_error{}</text>
-<polyline fill="none" stroke="black" points="321,-470.5 321,-516.5 "/>
-<text text-anchor="middle" x="363.5" y="-501.3" font-family="Times,serif" font-size="14.00">bereq.*</text>
-<polyline fill="none" stroke="black" points="321,-493.5 406,-493.5 "/>
-<text text-anchor="middle" x="363.5" y="-478.3" font-family="Times,serif" font-size="14.00">beresp.*</text>
-<polyline fill="none" stroke="black" points="164,-470.5 406,-470.5 "/>
-<text text-anchor="middle" x="224" y="-455.3" font-family="Times,serif" font-size="14.00">retry</text>
-<polyline fill="none" stroke="black" points="164,-447.5 284,-447.5 "/>
-<text text-anchor="middle" x="181.5" y="-432.3" font-family="Times,serif" font-size="14.00">fail</text>
-<polyline fill="none" stroke="black" points="199,-424.5 199,-447.5 "/>
-<text text-anchor="middle" x="222.5" y="-432.3" font-family="Times,serif" font-size="14.00">max?</text>
-<polyline fill="none" stroke="black" points="246,-424.5 246,-447.5 "/>
-<text text-anchor="middle" x="265" y="-432.3" font-family="Times,serif" font-size="14.00">ok?</text>
-<polyline fill="none" stroke="black" points="284,-424.5 284,-470.5 "/>
-<text text-anchor="middle" x="317" y="-443.8" font-family="Times,serif" font-size="14.00">abandon</text>
-<polyline fill="none" stroke="black" points="350,-424.5 350,-470.5 "/>
-<text text-anchor="middle" x="378" y="-443.8" font-family="Times,serif" font-size="14.00">deliver</text>
+<!-- FETCH_FAIL -->
+<g id="node15" class="node">
+<title>FETCH_FAIL</title>
+<polygon fill="#40e0d0" stroke="#40e0d0" points="163,-342.5 67,-342.5 67,-306.5 163,-306.5 163,-342.5"/>
+<text text-anchor="middle" x="115" y="-320.8" font-family="Times,serif" font-size="14.00" fill="#000000">FETCH_FAIL</text>
+</g>
+<!-- v_b_e->FETCH_FAIL -->
+<g id="edge22" class="edge">
+<title>v_b_e:s->FETCH_FAIL</title>
+<path fill="none" stroke="#000000" d="M218,-538C218,-464.3488 167.6624,-389.3334 137.3673,-350.8555"/>
+<polygon fill="#000000" stroke="#000000" points="139.8606,-348.3708 130.868,-342.7687 134.4044,-352.7559 139.8606,-348.3708"/>
+</g>
+<!-- v_b_e_retry -->
+<g id="node16" class="node">
+<title>v_b_e_retry</title>
+<text text-anchor="middle" x="258" y="-320.8" font-family="Times,serif" font-size="14.00" fill="#000000">RETRY</text>
+</g>
+<!-- v_b_e->v_b_e_retry -->
+<g id="edge21" class="edge">
+<title>v_b_e:retry->v_b_e_retry</title>
+<path fill="none" stroke="#a020f0" d="M260,-538C260,-471.6476 259.0221,-393.7007 258.4339,-352.8154"/>
+<polygon fill="#a020f0" stroke="#a020f0" points="261.9331,-352.7248 258.2866,-342.7773 254.9338,-352.8276 261.9331,-352.7248"/>
 </g>
 <!-- v_b_hdrs->v_b_e -->
-<g id="edge7" class="edge"><title>v_b_hdrs->v_b_e</title>
-<path fill="none" stroke="black" d="M310.848,-730.251C304.731,-719.217 298.422,-705.904 295,-693 282.598,-646.229 280.359,-591.583 281.083,-549.761"/>
-<polygon fill="black" stroke="black" points="284.584,-549.769 281.319,-539.69 277.586,-549.605 284.584,-549.769"/>
+<g id="edge8" class="edge">
+<title>v_b_hdrs->v_b_e</title>
+<path fill="none" stroke="#000000" d="M294.1279,-932.588C269.6299,-923.2697 249,-907.8862 249,-882.5 249,-882.5 249,-882.5 249,-691.5 249,-682.3009 250.2111,-672.7974 252.1296,-663.5141"/>
+<polygon fill="#000000" stroke="#000000" points="255.5902,-664.0867 254.4652,-653.5518 248.775,-662.4889 255.5902,-664.0867"/>
+</g>
+<!-- v_b_r -->
+<g id="node7" class="node">
+<title>v_b_r</title>
+<polygon fill="none" stroke="#000000" points="268.5,-729.5 268.5,-844.5 587.5,-844.5 587.5,-729.5 268.5,-729.5"/>
+<text text-anchor="middle" x="428" y="-829.3" font-family="Times,serif" font-size="14.00" fill="#000000">vbf_stp_startfetch:</text>
+<polyline fill="none" stroke="#000000" points="268.5,-821.5 587.5,-821.5 "/>
+<text text-anchor="middle" x="370.5" y="-794.8" font-family="Times,serif" font-size="14.00" fill="#000000">vcl_backend_response{}</text>
+<polyline fill="none" stroke="#000000" points="472.5,-775.5 472.5,-821.5 "/>
+<text text-anchor="middle" x="530" y="-806.3" font-family="Times,serif" font-size="14.00" fill="#000000">bereq.*</text>
+<polyline fill="none" stroke="#000000" points="472.5,-798.5 587.5,-798.5 "/>
+<text text-anchor="middle" x="530" y="-783.3" font-family="Times,serif" font-size="14.00" fill="#000000">beresp.*</text>
+<polyline fill="none" stroke="#000000" points="268.5,-775.5 587.5,-775.5 "/>
+<text text-anchor="middle" x="290" y="-748.8" font-family="Times,serif" font-size="14.00" fill="#000000">error</text>
+<polyline fill="none" stroke="#000000" points="311.5,-729.5 311.5,-775.5 "/>
+<text text-anchor="middle" x="329" y="-748.8" font-family="Times,serif" font-size="14.00" fill="#000000">fail</text>
+<polyline fill="none" stroke="#000000" points="346.5,-729.5 346.5,-775.5 "/>
+<text text-anchor="middle" x="388" y="-760.3" font-family="Times,serif" font-size="14.00" fill="#000000">retry</text>
+<polyline fill="none" stroke="#000000" points="346.5,-752.5 429.5,-752.5 "/>
+<text text-anchor="middle" x="370" y="-737.3" font-family="Times,serif" font-size="14.00" fill="#000000">max?</text>
+<polyline fill="none" stroke="#000000" points="393.5,-729.5 393.5,-752.5 "/>
+<text text-anchor="middle" x="411.5" y="-737.3" font-family="Times,serif" font-size="14.00" fill="#000000">ok?</text>
+<polyline fill="none" stroke="#000000" points="429.5,-729.5 429.5,-775.5 "/>
+<text text-anchor="middle" x="460.5" y="-748.8" font-family="Times,serif" font-size="14.00" fill="#000000">abandon</text>
+<polyline fill="none" stroke="#000000" points="491.5,-729.5 491.5,-775.5 "/>
+<text text-anchor="middle" x="539.5" y="-760.3" font-family="Times,serif" font-size="14.00" fill="#000000">deliver or pass</text>
+<polyline fill="none" stroke="#000000" points="491.5,-752.5 587.5,-752.5 "/>
+<text text-anchor="middle" x="513.5" y="-737.3" font-family="Times,serif" font-size="14.00" fill="#000000">304?</text>
+<polyline fill="none" stroke="#000000" points="535.5,-729.5 535.5,-752.5 "/>
+<text text-anchor="middle" x="561.5" y="-737.3" font-family="Times,serif" font-size="14.00" fill="#000000">other?</text>
+</g>
+<!-- v_b_hdrs->v_b_r -->
+<g id="edge7" class="edge">
+<title>v_b_hdrs->v_b_r</title>
+<path fill="none" stroke="#000000" stroke-width="2" d="M383.0384,-920.1114C389.1342,-902.0645 397.4654,-877.3995 405.3007,-854.2027"/>
+<polygon fill="#000000" stroke="#000000" stroke-width="2" points="408.6196,-855.3136 408.5039,-844.7194 401.9877,-853.0735 408.6196,-855.3136"/>
+</g>
+<!-- v_b_r->v_b_e -->
+<g id="edge9" class="edge">
+<title>v_b_r:s->v_b_e</title>
+<path fill="none" stroke="#000000" d="M290,-729C290,-707.7663 288.3384,-684.7157 286.2033,-663.8614"/>
+<polygon fill="#000000" stroke="#000000" points="289.6724,-663.3859 285.1223,-653.8179 282.7126,-664.135 289.6724,-663.3859"/>
 </g>
 <!-- v_b_r->v_b_e -->
-<g id="edge9" class="edge"><title>v_b_r:max->v_b_e</title>
-<path fill="none" stroke="black" d="M363,-577C363,-567.006 360.356,-557.506 356.043,-548.656"/>
-<polygon fill="black" stroke="black" points="358.941,-546.671 350.983,-539.676 352.843,-550.107 358.941,-546.671"/>
+<g id="edge11" class="edge">
+<title>v_b_r:max->v_b_e</title>
+<path fill="none" stroke="#000000" d="M370,-729C370,-704.608 359.3644,-681.5034 345.2866,-661.605"/>
+<polygon fill="#000000" stroke="#000000" points="348.0756,-659.4902 339.2906,-653.5679 342.465,-663.676 348.0756,-659.4902"/>
 </g>
 <!-- v_b_r_retry -->
-<g id="node8" class="node"><title>v_b_r_retry</title>
-<text text-anchor="middle" x="457" y="-478.3" font-family="Times,serif" font-size="14.00">RETRY</text>
+<g id="node8" class="node">
+<title>v_b_r_retry</title>
+<text text-anchor="middle" x="443" y="-592.3" font-family="Times,serif" font-size="14.00" fill="#000000">RETRY</text>
 </g>
 <!-- v_b_r->v_b_r_retry -->
-<g id="edge8" class="edge"><title>v_b_r:retry->v_b_r_retry</title>
-<path fill="none" stroke="purple" d="M405,-577C405,-562.594 423.938,-531.341 438.957,-508.822"/>
-<polygon fill="purple" stroke="purple" points="441.967,-510.618 444.677,-500.376 436.171,-506.693 441.967,-510.618"/>
+<g id="edge10" class="edge">
+<title>v_b_r:retry->v_b_r_retry</title>
+<path fill="none" stroke="#a020f0" d="M411,-729C411,-691.7258 423.0279,-650.1652 432.3354,-623.5842"/>
+<polygon fill="#a020f0" stroke="#a020f0" points="435.6303,-624.7647 435.7387,-614.1705 429.0473,-622.3848 435.6303,-624.7647"/>
 </g>
 <!-- vbf_stp_condfetch -->
-<g id="node9" class="node"><title>vbf_stp_condfetch</title>
-<polygon fill="none" stroke="grey" points="389,-313.5 389,-405.5 517,-405.5 517,-313.5 389,-313.5"/>
-<text text-anchor="middle" x="453" y="-390.3" font-family="Times,serif" font-size="14.00" fill="grey">vbf_stp_condfetch:</text>
-<polyline fill="none" stroke="grey" points="389,-382.5 517,-382.5 "/>
-<text text-anchor="middle" x="453" y="-367.3" font-family="Times,serif" font-size="14.00" fill="grey">copy obj attr</text>
-<polyline fill="none" stroke="grey" points="389,-359.5 517,-359.5 "/>
-<text text-anchor="middle" x="453" y="-344.3" font-family="Times,serif" font-size="14.00" fill="grey">steal body</text>
-<polyline fill="none" stroke="grey" points="389,-336.5 517,-336.5 "/>
-<text text-anchor="middle" x="430.5" y="-321.3" font-family="Times,serif" font-size="14.00" fill="grey">fetch_fail?</text>
-<polyline fill="none" stroke="grey" points="472,-313.5 472,-336.5 "/>
-<text text-anchor="middle" x="494.5" y="-321.3" font-family="Times,serif" font-size="14.00" fill="grey">ok?</text>
+<g id="node9" class="node">
+<title>vbf_stp_condfetch</title>
+<polygon fill="none" stroke="#c0c0c0" points="387.5,-427.5 387.5,-519.5 508.5,-519.5 508.5,-427.5 387.5,-427.5"/>
+<text text-anchor="middle" x="448" y="-504.3" font-family="Times,serif" font-size="14.00" fill="#c0c0c0">vbf_stp_condfetch:</text>
+<polyline fill="none" stroke="#c0c0c0" points="387.5,-496.5 508.5,-496.5 "/>
+<text text-anchor="middle" x="448" y="-481.3" font-family="Times,serif" font-size="14.00" fill="#c0c0c0">copy obj attr</text>
+<polyline fill="none" stroke="#c0c0c0" points="387.5,-473.5 508.5,-473.5 "/>
+<text text-anchor="middle" x="448" y="-458.3" font-family="Times,serif" font-size="14.00" fill="#c0c0c0">steal body</text>
+<polyline fill="none" stroke="#c0c0c0" points="387.5,-450.5 508.5,-450.5 "/>
+<text text-anchor="middle" x="427" y="-435.3" font-family="Times,serif" font-size="14.00" fill="#c0c0c0">fetch_fail?</text>
+<polyline fill="none" stroke="#c0c0c0" points="466.5,-427.5 466.5,-450.5 "/>
+<text text-anchor="middle" x="487.5" y="-435.3" font-family="Times,serif" font-size="14.00" fill="#c0c0c0">ok?</text>
 </g>
 <!-- v_b_r->vbf_stp_condfetch -->
-<g id="edge10" class="edge"><title>v_b_r:fetch_304:s->vbf_stp_condfetch</title>
-<path fill="none" stroke="black" d="M514,-577C514,-508.629 522.108,-487.979 498,-424 496.833,-420.902 495.477,-417.816 493.979,-414.767"/>
-<polygon fill="black" stroke="black" points="496.942,-412.889 489.106,-405.759 490.786,-416.22 496.942,-412.889"/>
+<g id="edge12" class="edge">
+<title>v_b_r:s->vbf_stp_condfetch</title>
+<path fill="none" stroke="#000000" d="M514,-729C514,-718.25 486.4736,-548.1733 483,-538 481.9502,-534.9255 480.7623,-531.8235 479.4742,-528.7301"/>
+<polygon fill="#000000" stroke="#000000" points="482.6277,-527.2082 475.3472,-519.5112 476.2387,-530.0684 482.6277,-527.2082"/>
 </g>
 <!-- vbf_stp_fetch -->
-<g id="node10" class="node"><title>vbf_stp_fetch</title>
-<polygon fill="none" stroke="grey" points="528.5,-436 528.5,-528 631.5,-528 631.5,-436 528.5,-436"/>
-<text text-anchor="middle" x="580" y="-512.8" font-family="Times,serif" font-size="14.00" fill="grey">vbf_stp_fetch:</text>
-<polyline fill="none" stroke="grey" points="528.5,-505 631.5,-505 "/>
-<text text-anchor="middle" x="580" y="-489.8" font-family="Times,serif" font-size="14.00" fill="grey">setup VFPs</text>
-<polyline fill="none" stroke="grey" points="528.5,-482 631.5,-482 "/>
-<text text-anchor="middle" x="580" y="-466.8" font-family="Times,serif" font-size="14.00" fill="grey">get object</text>
-<polyline fill="none" stroke="grey" points="528.5,-459 631.5,-459 "/>
-<text text-anchor="middle" x="553.5" y="-443.8" font-family="Times,serif" font-size="14.00" fill="grey">error?</text>
-<polyline fill="none" stroke="grey" points="578.5,-436 578.5,-459 "/>
-<text text-anchor="middle" x="605" y="-443.8" font-family="Times,serif" font-size="14.00" fill="grey">body?</text>
+<g id="node10" class="node">
+<title>vbf_stp_fetch</title>
+<polygon fill="none" stroke="#c0c0c0" points="512.5,-550 512.5,-642 611.5,-642 611.5,-550 512.5,-550"/>
+<text text-anchor="middle" x="562" y="-626.8" font-family="Times,serif" font-size="14.00" fill="#c0c0c0">vbf_stp_fetch:</text>
+<polyline fill="none" stroke="#c0c0c0" points="512.5,-619 611.5,-619 "/>
+<text text-anchor="middle" x="562" y="-603.8" font-family="Times,serif" font-size="14.00" fill="#c0c0c0">setup VFPs</text>
+<polyline fill="none" stroke="#c0c0c0" points="512.5,-596 611.5,-596 "/>
+<text text-anchor="middle" x="562" y="-580.8" font-family="Times,serif" font-size="14.00" fill="#c0c0c0">get object</text>
+<polyline fill="none" stroke="#c0c0c0" points="512.5,-573 611.5,-573 "/>
+<text text-anchor="middle" x="537" y="-557.8" font-family="Times,serif" font-size="14.00" fill="#c0c0c0">error?</text>
+<polyline fill="none" stroke="#c0c0c0" points="561.5,-550 561.5,-573 "/>
+<text text-anchor="middle" x="586.5" y="-557.8" font-family="Times,serif" font-size="14.00" fill="#c0c0c0">body?</text>
 </g>
 <!-- v_b_r->vbf_stp_fetch -->
-<g id="edge11" class="edge"><title>v_b_r:non_304:s->vbf_stp_fetch</title>
-<path fill="none" stroke="black" d="M563,-577C563,-564.307 564.52,-550.801 566.65,-538.103"/>
-<polygon fill="black" stroke="black" points="570.119,-538.59 568.472,-528.124 563.233,-537.332 570.119,-538.59"/>
-</g>
-<!-- FETCH_DONE -->
-<g id="node13" class="node"><title>FETCH_DONE</title>
-<polygon fill="turquoise" stroke="turquoise" points="420.5,-44 309.5,-44 309.5,-8 420.5,-8 420.5,-44"/>
-<text text-anchor="middle" x="365" y="-22.3" font-family="Times,serif" font-size="14.00">FETCH_DONE</text>
-</g>
-<!-- v_b_e->FETCH_DONE -->
-<g id="edge18" class="edge"><title>v_b_e:deliver->FETCH_DONE</title>
-<path fill="none" stroke="black" d="M378,-424C378,-309.281 327.238,-283.213 338,-169 341.799,-128.68 351.538,-82.7642 358.218,-54.3309"/>
-<polygon fill="black" stroke="black" points="361.686,-54.8777 360.61,-44.3377 354.879,-53.2483 361.686,-54.8777"/>
-<text text-anchor="middle" x="386" y="-172.8" font-family="Times,serif" font-size="14.00">"backend synth"</text>
-</g>
-<!-- FETCH_FAIL -->
-<g id="node15" class="node"><title>FETCH_FAIL</title>
-<polygon fill="turquoise" stroke="turquoise" points="170.5,-266.5 67.5,-266.5 67.5,-230.5 170.5,-230.5 170.5,-266.5"/>
-<text text-anchor="middle" x="119" y="-244.8" font-family="Times,serif" font-size="14.00">FETCH_FAIL</text>
-</g>
-<!-- v_b_e->FETCH_FAIL -->
-<g id="edge20" class="edge"><title>v_b_e:max:s->FETCH_FAIL</title>
-<path fill="none" stroke="black" d="M222,-424C222,-363.679 175.791,-305.878 145.274,-274.283"/>
-<polygon fill="black" stroke="black" points="147.416,-271.471 137.892,-266.829 142.442,-276.397 147.416,-271.471"/>
-</g>
-<!-- v_b_e_retry -->
-<g id="node16" class="node"><title>v_b_e_retry</title>
-<text text-anchor="middle" x="265" y="-244.8" font-family="Times,serif" font-size="14.00">RETRY</text>
-</g>
-<!-- v_b_e->v_b_e_retry -->
-<g id="edge19" class="edge"><title>v_b_e:retry->v_b_e_retry</title>
-<path fill="none" stroke="purple" d="M265,-424C265,-372.06 265,-311.425 265,-277.036"/>
-<polygon fill="purple" stroke="purple" points="268.5,-276.837 265,-266.837 261.5,-276.837 268.5,-276.837"/>
+<g id="edge13" class="edge">
+<title>v_b_r:s->vbf_stp_fetch</title>
+<path fill="none" stroke="#000000" d="M562,-729C562,-703.8578 562,-676.042 562,-652.3756"/>
+<polygon fill="#000000" stroke="#000000" points="565.5001,-652.1637 562,-642.1637 558.5001,-652.1638 565.5001,-652.1637"/>
 </g>
 <!-- vbf_stp_fetchend -->
-<g id="node12" class="node"><title>vbf_stp_fetchend</title>
-<polygon fill="none" stroke="grey" points="388,-81.5 388,-150.5 556,-150.5 556,-81.5 388,-81.5"/>
-<text text-anchor="middle" x="472" y="-135.3" font-family="Times,serif" font-size="14.00" fill="grey">vbf_stp_fetchend:</text>
-<polyline fill="none" stroke="grey" points="388,-127.5 556,-127.5 "/>
-<text text-anchor="middle" x="472" y="-112.3" font-family="Times,serif" font-size="14.00" fill="grey">finalize object and director</text>
-<polyline fill="none" stroke="grey" points="388,-104.5 556,-104.5 "/>
-<text text-anchor="middle" x="472" y="-89.3" font-family="Times,serif" font-size="14.00" fill="grey">done</text>
+<g id="node12" class="node">
+<title>vbf_stp_fetchend</title>
+<polygon fill="none" stroke="#c0c0c0" points="401.5,-119.5 401.5,-188.5 564.5,-188.5 564.5,-119.5 401.5,-119.5"/>
+<text text-anchor="middle" x="483" y="-173.3" font-family="Times,serif" font-size="14.00" fill="#c0c0c0">vbf_stp_fetchend:</text>
+<polyline fill="none" stroke="#c0c0c0" points="401.5,-165.5 564.5,-165.5 "/>
+<text text-anchor="middle" x="483" y="-150.3" font-family="Times,serif" font-size="14.00" fill="#c0c0c0">finalize object and director</text>
+<polyline fill="none" stroke="#c0c0c0" points="401.5,-142.5 564.5,-142.5 "/>
+<text text-anchor="middle" x="483" y="-127.3" font-family="Times,serif" font-size="14.00" fill="#c0c0c0">done</text>
 </g>
 <!-- vbf_stp_condfetch->vbf_stp_fetchend -->
-<g id="edge16" class="edge"><title>vbf_stp_condfetch:ok:s->vbf_stp_fetchend</title>
-<path fill="none" stroke="black" d="M495,-313C495,-286.857 454.4,-316.126 439,-295 410.205,-255.499 428.579,-198.293 447.436,-159.476"/>
-<polygon fill="black" stroke="black" points="450.578,-161.019 451.957,-150.514 444.328,-157.866 450.578,-161.019"/>
+<g id="edge18" class="edge">
+<title>vbf_stp_condfetch:s->vbf_stp_fetchend</title>
+<path fill="none" stroke="#000000" d="M488,-427.5C488,-389.8893 440.3317,-405.344 425,-371 408.1508,-333.2568 416.0301,-318.3483 425,-278 431.2607,-249.8383 444.6245,-220.5039 456.9478,-197.4406"/>
+<polygon fill="#000000" stroke="#000000" points="460.0525,-199.0578 461.7812,-188.605 453.9113,-195.6983 460.0525,-199.0578"/>
 </g>
 <!-- vbf_stp_fetchbody -->
-<g id="node11" class="node"><title>vbf_stp_fetchbody</title>
-<polygon fill="none" stroke="grey" points="448,-202.5 448,-294.5 612,-294.5 612,-202.5 448,-202.5"/>
-<text text-anchor="middle" x="530" y="-279.3" font-family="Times,serif" font-size="14.00" fill="grey">vbf_stp_fetchbody:</text>
-<polyline fill="none" stroke="grey" points="448,-271.5 612,-271.5 "/>
-<text text-anchor="middle" x="530" y="-256.3" font-family="Times,serif" font-size="14.00" fill="grey">get storage</text>
-<polyline fill="none" stroke="grey" points="448,-248.5 612,-248.5 "/>
-<text text-anchor="middle" x="530" y="-233.3" font-family="Times,serif" font-size="14.00" fill="grey">read body, run VFPs</text>
-<polyline fill="none" stroke="grey" points="448,-225.5 612,-225.5 "/>
-<text text-anchor="middle" x="486" y="-210.3" font-family="Times,serif" font-size="14.00" fill="grey">fetch_fail?</text>
-<polyline fill="none" stroke="grey" points="524,-202.5 524,-225.5 "/>
-<text text-anchor="middle" x="549" y="-210.3" font-family="Times,serif" font-size="14.00" fill="grey">error?</text>
-<polyline fill="none" stroke="grey" points="574,-202.5 574,-225.5 "/>
-<text text-anchor="middle" x="593" y="-210.3" font-family="Times,serif" font-size="14.00" fill="grey">ok?</text>
+<g id="node11" class="node">
+<title>vbf_stp_fetchbody</title>
+<polygon fill="none" stroke="#c0c0c0" points="433.5,-278.5 433.5,-370.5 592.5,-370.5 592.5,-278.5 433.5,-278.5"/>
+<text text-anchor="middle" x="513" y="-355.3" font-family="Times,serif" font-size="14.00" fill="#c0c0c0">vbf_stp_fetchbody:</text>
+<polyline fill="none" stroke="#c0c0c0" points="433.5,-347.5 592.5,-347.5 "/>
+<text text-anchor="middle" x="513" y="-332.3" font-family="Times,serif" font-size="14.00" fill="#c0c0c0">get storage</text>
+<polyline fill="none" stroke="#c0c0c0" points="433.5,-324.5 592.5,-324.5 "/>
+<text text-anchor="middle" x="513" y="-309.3" font-family="Times,serif" font-size="14.00" fill="#c0c0c0">read body, run VFPs</text>
+<polyline fill="none" stroke="#c0c0c0" points="433.5,-301.5 592.5,-301.5 "/>
+<text text-anchor="middle" x="470.5" y="-286.3" font-family="Times,serif" font-size="14.00" fill="#c0c0c0">fetch_fail?</text>
+<polyline fill="none" stroke="#c0c0c0" points="507.5,-278.5 507.5,-301.5 "/>
+<text text-anchor="middle" x="532" y="-286.3" font-family="Times,serif" font-size="14.00" fill="#c0c0c0">error?</text>
+<polyline fill="none" stroke="#c0c0c0" points="556.5,-278.5 556.5,-301.5 "/>
+<text text-anchor="middle" x="574.5" y="-286.3" font-family="Times,serif" font-size="14.00" fill="#c0c0c0">ok?</text>
 </g>
 <!-- vbf_stp_fetch->vbf_stp_fetchbody -->
-<g id="edge13" class="edge"><title>vbf_stp_fetch:body:s->vbf_stp_fetchbody</title>
-<path fill="none" stroke="black" d="M605,-435C605,-388.245 584.268,-339.378 564.605,-303.543"/>
-<polygon fill="black" stroke="black" points="567.596,-301.722 559.642,-294.723 561.495,-305.154 567.596,-301.722"/>
+<g id="edge15" class="edge">
+<title>vbf_stp_fetch:s->vbf_stp_fetchbody</title>
+<path fill="none" stroke="#000000" d="M587,-550C587,-489.6065 562.7413,-424.4469 542.0029,-379.7771"/>
+<polygon fill="#000000" stroke="#000000" points="545.0838,-378.1052 537.6409,-370.5651 538.7572,-381.101 545.0838,-378.1052"/>
 </g>
 <!-- vbf_stp_fetch->vbf_stp_fetchend -->
-<g id="edge14" class="edge"><title>vbf_stp_fetch:body:s->vbf_stp_fetchend</title>
-<path fill="none" stroke="black" d="M605,-435C605,-331.201 658.43,-298.816 621,-202 611.149,-176.518 589.225,-158.384 565.146,-145.604"/>
-<polygon fill="black" stroke="black" points="566.706,-142.471 556.196,-141.134 563.578,-148.733 566.706,-142.471"/>
+<g id="edge16" class="edge">
+<title>vbf_stp_fetch:s->vbf_stp_fetchend</title>
+<path fill="none" stroke="#000000" d="M587,-550C587,-486.2129 611,-472.2871 611,-408.5 611,-408.5 611,-408.5 611,-233.5 611,-209.5885 594.6814,-192.6171 573.6976,-180.6783"/>
+<polygon fill="#000000" stroke="#000000" points="575.2732,-177.5526 564.7891,-176.0252 572.0324,-183.7572 575.2732,-177.5526"/>
 </g>
 <!-- vbf_stp_fetchbody->vbf_stp_fetchend -->
-<g id="edge12" class="edge"><title>vbf_stp_fetchbody:ok:s->vbf_stp_fetchend</title>
-<path fill="none" stroke="black" d="M593,-202C593,-181.262 580.952,-165.148 564.459,-152.805"/>
-<polygon fill="black" stroke="black" points="566.268,-149.802 556.039,-147.044 562.316,-155.579 566.268,-149.802"/>
+<g id="edge14" class="edge">
+<title>vbf_stp_fetchbody:s->vbf_stp_fetchend</title>
+<path fill="none" stroke="#000000" d="M575,-278.5C575,-246.7479 555.4055,-217.7865 534.3022,-195.8028"/>
+<polygon fill="#000000" stroke="#000000" points="536.6619,-193.2128 527.1138,-188.621 531.7144,-198.1649 536.6619,-193.2128"/>
 </g>
 <!-- vbf_stp_fetchend->FETCH_DONE -->
-<g id="edge15" class="edge"><title>vbf_stp_fetchend:done:s->FETCH_DONE</title>
-<path fill="none" stroke="black" d="M472,-81C472,-58.3323 452.624,-45.1781 430.363,-37.5453"/>
-<polygon fill="black" stroke="black" points="431.28,-34.1659 420.694,-34.6006 429.24,-40.8622 431.28,-34.1659"/>
-</g>
-<!-- error -->
-<g id="node14" class="node"><title>error</title>
-<text text-anchor="middle" x="119" y="-478.3" font-family="Times,serif" font-size="14.00">error</text>
-</g>
-<!-- error->FETCH_FAIL -->
-<g id="edge17" class="edge"><title>error->FETCH_FAIL</title>
-<path fill="none" stroke="black" d="M119,-463.977C119,-424.176 119,-324.764 119,-276.558"/>
-<polygon fill="black" stroke="black" points="122.5,-276.548 119,-266.548 115.5,-276.548 122.5,-276.548"/>
+<g id="edge17" class="edge">
+<title>vbf_stp_fetchend:s->FETCH_DONE</title>
+<path fill="none" stroke="#000000" d="M483,-119C483,-84.0415 451.1405,-60.6773 419.5902,-46.1107"/>
+<polygon fill="#000000" stroke="#000000" points="420.8522,-42.8427 410.287,-42.0514 418.0528,-49.2586 420.8522,-42.8427"/>
+</g>
+<!-- fail -->
+<g id="node14" class="node">
+<title>fail</title>
+<text text-anchor="middle" x="115" y="-592.3" font-family="Times,serif" font-size="14.00" fill="#000000">fail</text>
+</g>
+<!-- fail->FETCH_FAIL -->
+<g id="edge19" class="edge">
+<title>fail->FETCH_FAIL</title>
+<path fill="none" stroke="#000000" d="M115,-577.7645C115,-531.3959 115,-408.719 115,-352.8885"/>
+<polygon fill="#000000" stroke="#000000" points="118.5001,-352.6561 115,-342.6561 111.5001,-352.6561 118.5001,-352.6561"/>
 </g>
 <!-- abandon -->
-<g id="node17" class="node"><title>abandon</title>
-<text text-anchor="middle" x="41" y="-478.3" font-family="Times,serif" font-size="14.00">abandon</text>
+<g id="node17" class="node">
+<title>abandon</title>
+<text text-anchor="middle" x="39" y="-592.3" font-family="Times,serif" font-size="14.00" fill="#000000">abandon</text>
 </g>
 <!-- abandon->FETCH_FAIL -->
-<g id="edge21" class="edge"><title>abandon->FETCH_FAIL</title>
-<path fill="none" stroke="black" d="M46.7355,-463.977C60.1741,-424.092 93.7819,-324.346 109.985,-276.255"/>
-<polygon fill="black" stroke="black" points="113.38,-277.142 113.256,-266.548 106.746,-274.907 113.38,-277.142"/>
+<g id="edge23" class="edge">
+<title>abandon->FETCH_FAIL</title>
+<path fill="none" stroke="#000000" d="M44.1046,-577.7645C57.1114,-531.2993 91.5681,-408.2075 107.1507,-352.5404"/>
+<polygon fill="#000000" stroke="#000000" points="110.5924,-353.2294 109.9176,-342.6561 103.8515,-351.3424 110.5924,-353.2294"/>
 </g>
 </g>
 </svg>
diff --git a/doc/sphinx/users-guide/vcl-built-in-subs.rst b/doc/sphinx/users-guide/vcl-built-in-subs.rst
index 0315b4838..fd5a58104 100644
--- a/doc/sphinx/users-guide/vcl-built-in-subs.rst
+++ b/doc/sphinx/users-guide/vcl-built-in-subs.rst
@@ -356,6 +356,11 @@ The `vcl_backend_fetch` subroutine may terminate with calling
   ``fetch``
     Fetch the object from the backend.
 
+  ``error(status code, reason)``
+    Transition to :ref:`vcl_backend_error` with ``beresp.status`` and
+    ``beresp.reason`` being preset to the arguments of ``error()`` if
+    arguments are provided.
+
 Before calling `vcl_backend_fetch`, Varnish core prepares the `bereq`
 backend request as follows:
 
@@ -417,6 +422,11 @@ The `vcl_backend_response` subroutine may terminate with calling
     lookups hitting this object will be turned into passed transactions,
     as if ``vcl_recv`` had returned ``pass``.
 
+  ``error(status code, reason)``
+    Transition to :ref:`vcl_backend_error` with ``beresp.status`` and
+    ``beresp.reason`` being preset to the arguments of ``error()`` if
+    arguments are provided.
+
 304 handling
 ~~~~~~~~~~~~
 
diff --git a/lib/libvcc/generate.py b/lib/libvcc/generate.py
index fb464bc39..d662375fd 100755
--- a/lib/libvcc/generate.py
+++ b/lib/libvcc/generate.py
@@ -129,11 +129,11 @@ returns = (
 
     ('backend_fetch',
      "B",
-     ('fail', 'fetch', 'abandon')
+     ('fail', 'fetch', 'abandon', 'error')
     ),
     ('backend_response',
      "B",
-     ('fail', 'deliver', 'retry', 'abandon', 'pass')
+     ('fail', 'deliver', 'retry', 'abandon', 'pass', 'error')
     ),
     ('backend_error',
      "B",
diff --git a/lib/libvcc/vcc_action.c b/lib/libvcc/vcc_action.c
index 1e218cb4f..9ce0e6312 100644
--- a/lib/libvcc/vcc_action.c
+++ b/lib/libvcc/vcc_action.c
@@ -335,7 +335,7 @@ vcc_act_return(struct vcc *tl, struct token *t, struct symbol *sym)
 	vcc_ProcAction(tl->curproc, hand, tl->t);
 	vcc_NextToken(tl);
 	if (tl->t->tok == '(') {
-		if (hand == VCL_RET_SYNTH)
+		if (hand == VCL_RET_SYNTH || hand == VCL_RET_ERROR)
 			vcc_act_return_synth(tl);
 		else if (hand == VCL_RET_VCL)
 			vcc_act_return_vcl(tl);


More information about the varnish-commit mailing list