[master] 0ea8328 Further split the "how" from the "what" of response delivery.

Poul-Henning Kamp phk at varnish-cache.org
Wed Sep 4 15:14:24 CEST 2013


commit 0ea83286f2aca91d4f8f33c4589dd3e70aebfac7
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Wed Sep 4 13:12:45 2013 +0000

    Further split the "how" from the "what" of response delivery.
    
    Here be dragons.   For instance that if a HEAD is passed, we should
    let the Content-Length: unmolested through, whereas normally C-L is a
    property of the protocol delivery of the HTTP response.

diff --git a/bin/varnishd/cache/cache_fetch.c b/bin/varnishd/cache/cache_fetch.c
index 8b806be..4c926e9 100644
--- a/bin/varnishd/cache/cache_fetch.c
+++ b/bin/varnishd/cache/cache_fetch.c
@@ -306,8 +306,7 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo)
 	if (bo->htc.body_status == BS_NONE)
 		bo->do_stream = 0;
 
-	l = http_EstimateWS(bo->beresp,
-	    bo->uncacheable ? HTTPH_R_PASS : HTTPH_A_INS, &nhttp);
+	l = 0;
 
 	/* Create Vary instructions */
 	if (!(bo->fetch_objcore->flags & OC_F_PRIVATE)) {
@@ -331,18 +330,15 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo)
 			AZ(vary);
 	}
 
+	l += http_EstimateWS(bo->beresp,
+	    bo->uncacheable ? HTTPH_R_PASS : HTTPH_A_INS, &nhttp);
+
 	if (bo->uncacheable)
 		bo->fetch_objcore->flags |= OC_F_PASS;
 
 	if (bo->exp.ttl < cache_param->shortlived || bo->uncacheable == 1)
 		bo->storage_hint = TRANSIENT_STORAGE;
 
-	/*
-	 * Space for producing a Content-Length: header including padding
-	 * A billion gigabytes is enough for anybody.
-	 */
-	l += strlen("Content-Length: XxxXxxXxxXxxXxxXxx") + sizeof(void *);
-
 	AZ(bo->stats);
 	bo->stats = &wrk->stats;
 	AN(bo->fetch_objcore);
diff --git a/bin/varnishd/cache/cache_http1_fetch.c b/bin/varnishd/cache/cache_http1_fetch.c
index 01511e8..e8dbdaa 100644
--- a/bin/varnishd/cache/cache_http1_fetch.c
+++ b/bin/varnishd/cache/cache_http1_fetch.c
@@ -311,7 +311,6 @@ V1F_fetch_body(struct worker *wrk, struct busyobj *bo)
 {
 	int cls;
 	struct storage *st;
-	int mklen;
 	ssize_t cl;
 	struct http_conn *htc;
 	struct object *obj;
@@ -342,10 +341,8 @@ V1F_fetch_body(struct worker *wrk, struct busyobj *bo)
 	cls = bo->should_close;
 	switch (htc->body_status) {
 	case BS_NONE:
-		mklen = 0;
 		break;
 	case BS_ZERO:
-		mklen = 1;
 		break;
 	case BS_LENGTH:
 		cl = vbf_fetch_number(bo->h_content_length, 10);
@@ -353,7 +350,6 @@ V1F_fetch_body(struct worker *wrk, struct busyobj *bo)
 		bo->vfp->begin(bo, cl);
 		if (bo->state == BOS_FETCHING && cl > 0)
 			cls |= vbf_fetch_straight(bo, htc, cl);
-		mklen = 1;
 		if (bo->vfp->end(bo))
 			assert(bo->state == BOS_FAILED);
 		break;
@@ -361,7 +357,6 @@ V1F_fetch_body(struct worker *wrk, struct busyobj *bo)
 		bo->vfp->begin(bo, cl > 0 ? cl : 0);
 		if (bo->state == BOS_FETCHING)
 			cls |= vbf_fetch_chunked(bo, htc);
-		mklen = 1;
 		if (bo->vfp->end(bo))
 			assert(bo->state == BOS_FAILED);
 		break;
@@ -369,17 +364,14 @@ V1F_fetch_body(struct worker *wrk, struct busyobj *bo)
 		bo->vfp->begin(bo, cl > 0 ? cl : 0);
 		if (bo->state == BOS_FETCHING)
 			vbf_fetch_eof(bo, htc);
-		mklen = 1;
 		cls = 1;
 		if (bo->vfp->end(bo))
 			assert(bo->state == BOS_FAILED);
 		break;
 	case BS_ERROR:
 		cls |= VFP_Error(bo, "error incompatible Transfer-Encoding");
-		mklen = 0;
 		break;
 	default:
-		mklen = 0;
 		INCOMPL();
 	}
 	AZ(bo->vgz_rx);
@@ -401,9 +393,8 @@ V1F_fetch_body(struct worker *wrk, struct busyobj *bo)
 
 	bo->vfp = NULL;
 
-	VSLb(bo->vsl, SLT_Fetch_Body, "%u(%s) cls %d mklen %d",
-	    htc->body_status, body_status_2str(htc->body_status),
-	    cls, mklen);
+	VSLb(bo->vsl, SLT_Fetch_Body, "%u(%s) cls %d",
+	    htc->body_status, body_status_2str(htc->body_status), cls);
 
 	http_Teardown(bo->bereq);
 	http_Teardown(bo->beresp);
@@ -440,12 +431,6 @@ V1F_fetch_body(struct worker *wrk, struct busyobj *bo)
 			else
 				assert(uu == obj->len);
 		}
-
-		if (mklen > 0) {
-			http_Unset(obj->http, H_Content_Length);
-			http_PrintfHeader(obj->http,
-			    "Content-Length: %zd", obj->len);
-		}
 	}
 	bo->stats = NULL;
 }
diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c
index bfde6f7..9ed176e 100644
--- a/bin/varnishd/cache/cache_req_fsm.c
+++ b/bin/varnishd/cache/cache_req_fsm.c
@@ -169,45 +169,6 @@ cnt_deliver(struct worker *wrk, struct req *req)
 
 	assert(req->obj->objcore->refcnt > 0);
 
-	req->res_mode = 0;
-
-	if (!req->disable_esi && req->obj->esidata != NULL) {
-		/* In ESI mode, we can't know the aggregate length */
-		req->res_mode &= ~RES_LEN;
-		req->res_mode |= RES_ESI;
-	} else if (req->obj->objcore->busyobj == NULL) {
-		req->res_mode |= RES_LEN;
-	}
-
-	if (req->esi_level > 0) {
-		/* Included ESI object, always CHUNKED or EOF */
-		req->res_mode &= ~RES_LEN;
-		req->res_mode |= RES_ESI_CHILD;
-	}
-
-	if (cache_param->http_gzip_support && req->obj->gziped &&
-	    !RFC2616_Req_Gzip(req->http)) {
-		/*
-		 * We don't know what it uncompresses to
-		 * XXX: we could cache that
-		 */
-		req->res_mode &= ~RES_LEN;
-		req->res_mode |= RES_GUNZIP;
-	}
-
-	if (!(req->res_mode & (RES_LEN|RES_CHUNKED|RES_EOF))) {
-		/* We havn't chosen yet, do so */
-		if (!req->wantbody) {
-			/* Nothing */
-		} else if (req->http->protover >= 11) {
-			req->res_mode |= RES_CHUNKED;
-		} else {
-			req->res_mode |= RES_EOF;
-			req->doclose = SC_TX_EOF;
-		}
-	}
-	VSLb(req->vsl, SLT_Debug, "RES_MODE %x", req->res_mode);
-
 	req->t_resp = W_TIM_real(wrk);
 	if (!(req->obj->objcore->flags & OC_F_PRIVATE)) {
 		if ((req->t_resp - req->obj->last_lru) >
@@ -224,7 +185,7 @@ cnt_deliver(struct worker *wrk, struct req *req)
 	http_FilterResp(req->obj->http, req->resp, 0);
 
 	http_Unset(req->resp, H_Date);
-	VTIM_format(VTIM_real(), time_str);
+	VTIM_format(req->t_resp, time_str);
 	http_PrintfHeader(req->resp, "Date: %s", time_str);
 
 	if (req->wrk->stats.cache_hit)
@@ -239,17 +200,15 @@ cnt_deliver(struct worker *wrk, struct req *req)
 	    req->obj->exp.age + req->t_resp - req->obj->exp.entered);
 
 	http_SetHeader(req->resp, "Via: 1.1 varnish");
-	
 
 	VCL_deliver_method(req->vcl, wrk, req, NULL, req->http->ws);
 
-	RES_BuildHttp(req);
-
 	while (req->obj->objcore->busyobj) {
 		VSLb(req->vsl, SLT_Debug, "HERE %s %d", __func__, __LINE__);
 		(void)usleep(10000);
 	}
 
+	RES_BuildHttp(req);
 
 	/* Stop the insanity before it turns "Hotel California" on us */
 	if (req->restarts >= cache_param->max_restarts)
diff --git a/bin/varnishd/cache/cache_response.c b/bin/varnishd/cache/cache_response.c
index 0dee670..c56932e 100644
--- a/bin/varnishd/cache/cache_response.c
+++ b/bin/varnishd/cache/cache_response.c
@@ -108,13 +108,57 @@ RES_BuildHttp(struct req *req)
 	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
 	CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC);
 
-	if (!(req->res_mode & RES_LEN)) {
-		http_Unset(req->resp, H_Content_Length);
-	} else if (cache_param->http_range_support) {
-		/* We only accept ranges if we know the length */
-		http_SetHeader(req->resp, "Accept-Ranges: bytes");
+	req->res_mode = 0;
+
+	if (!req->disable_esi && req->obj->esidata != NULL) {
+		/* In ESI mode, we can't know the aggregate length */
+		req->res_mode &= ~RES_LEN;
+		req->res_mode |= RES_ESI;
+	} else if (req->obj->objcore->busyobj == NULL) {
+		/* XXX: Not happy with this convoluted test */
+		req->res_mode |= RES_LEN;
+		if (!(req->obj->objcore->flags & OC_F_PASS) ||
+		    req->obj->len != 0) {
+			http_Unset(req->resp, H_Content_Length);
+			http_PrintfHeader(req->resp,
+			    "Content-Length: %zd", req->obj->len);
+		}
+		if (cache_param->http_range_support)
+			http_SetHeader(req->resp, "Accept-Ranges: bytes");
+	}
+
+	if (req->esi_level > 0) {
+		/* Included ESI object, always CHUNKED or EOF */
+		req->res_mode &= ~RES_LEN;
+		req->res_mode |= RES_ESI_CHILD;
+	}
+
+	if (cache_param->http_gzip_support && req->obj->gziped &&
+	    !RFC2616_Req_Gzip(req->http)) {
+		/*
+		 * We don't know what it uncompresses to
+		 * XXX: we could cache that
+		 */
+		req->res_mode &= ~RES_LEN;
+		req->res_mode |= RES_GUNZIP;
 	}
 
+	if (!(req->res_mode & (RES_LEN|RES_CHUNKED|RES_EOF))) {
+		/* We havn't chosen yet, do so */
+		if (!req->wantbody) {
+			/* Nothing */
+		} else if (req->http->protover >= 11) {
+			req->res_mode |= RES_CHUNKED;
+		} else {
+			req->res_mode |= RES_EOF;
+			req->doclose = SC_TX_EOF;
+		}
+	}
+	VSLb(req->vsl, SLT_Debug, "RES_MODE %x", req->res_mode);
+
+	if (!(req->res_mode & RES_LEN))
+		http_Unset(req->resp, H_Content_Length);
+
 	if (req->res_mode & RES_GUNZIP)
 		http_Unset(req->resp, H_Content_Encoding);
 
diff --git a/bin/varnishd/cache/cache_vrt.c b/bin/varnishd/cache/cache_vrt.c
index de2cf78..36b2a43 100644
--- a/bin/varnishd/cache/cache_vrt.c
+++ b/bin/varnishd/cache/cache_vrt.c
@@ -419,8 +419,6 @@ VRT_synth_page(const struct vrt_ctx *ctx, unsigned flags, const char *str, ...)
 	va_end(ap);
 	SMS_Finish(ctx->req->obj);
 	http_Unset(ctx->req->obj->http, H_Content_Length);
-	http_PrintfHeader(ctx->req->obj->http,
-	    "Content-Length: %zd", ctx->req->obj->len);
 }
 
 /*--------------------------------------------------------------------*/



More information about the varnish-commit mailing list