commit 3c63ade0a6f74eeebfddda1fa1bbc2c41527677d
Author: Martin Blix Grydeland <martin@varnish-software.com>
Date:   Thu Aug 4 21:31:57 2011 +0200

    Don't attempt to do_stream when the conditions for a 304 is in place.
    
    Factor out the RES_Check_Conds() so we can do an early check if
    conditions are met.
    
    Problem spotted by DocWilco.
    
    Fixes: #972

diff --git a/bin/varnishd/cache.h b/bin/varnishd/cache.h
index a875071..4bb8fb1 100644
--- a/bin/varnishd/cache.h
+++ b/bin/varnishd/cache.h
@@ -891,6 +891,7 @@ void WSL_Flush(struct worker *w, int overflow);
 #endif
 
 /* cache_response.c */
+int RES_Check_Conds(struct sess *sp);
 void RES_BuildHttp(struct sess *sp);
 void RES_WriteObj(struct sess *sp);
 void RES_StreamStart(struct sess *sp);
diff --git a/bin/varnishd/cache_center.c b/bin/varnishd/cache_center.c
index f93a61b..9e84b45 100644
--- a/bin/varnishd/cache_center.c
+++ b/bin/varnishd/cache_center.c
@@ -803,6 +803,9 @@ cnt_fetchbody(struct sess *sp)
 
 	assert(WRW_IsReleased(sp->wrk));
 
+	if (sp->wrk->do_stream && RES_Check_Conds(sp))
+		sp->wrk->do_stream = 0;
+
 	if (sp->wrk->do_stream) {
 		sp->step = STP_PREPRESP;
 		return (0);
diff --git a/bin/varnishd/cache_response.c b/bin/varnishd/cache_response.c
index 4788a23..903fb7a 100644
--- a/bin/varnishd/cache_response.c
+++ b/bin/varnishd/cache_response.c
@@ -85,12 +85,12 @@ res_do_304(struct sess *sp)
 
 /*--------------------------------------------------------------------*/
 
-static int
-res_do_conds(struct sess *sp)
+int
+RES_Check_Conds(struct sess *sp)
 {
 	char *p, *e;
 	double ims;
-	int do_cond = 0;
+	int can_cond = 0;
 
 	/* RFC 2616 13.3.4 states we need to match both ETag
 	   and If-Modified-Since if present*/
@@ -103,21 +103,17 @@ res_do_conds(struct sess *sp)
 			return (0);
 		if (sp->obj->last_modified > ims)
 			return (0);
-		do_cond = 1;
+		can_cond = 1;
 	}
 
 	if (http_GetHdr(sp->http, H_If_None_Match, &p) &&
 	    http_GetHdr(sp->obj->http, H_ETag, &e)) {
 		if (strcmp(p,e) != 0)
 			return (0);
-		do_cond = 1;
+		can_cond = 1;
 	}
 
-	if (do_cond == 1) {
-		res_do_304(sp);
-		return (1);
-	}
-	return (0);
+	return (can_cond);
 }
 
 /*--------------------------------------------------------------------*/
@@ -195,8 +191,11 @@ RES_BuildHttp(struct sess *sp)
 
 	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
 
-	if (sp->obj->response == 200 && sp->http->conds && res_do_conds(sp))
+	if (sp->obj->response == 200 && sp->http->conds && 
+	    RES_Check_Conds(sp)) {
+		res_do_304(sp);
 		return;
+	}
 
 	http_ClrHeader(sp->wrk->resp);
 	sp->wrk->resp->logtag = HTTP_Tx;
diff --git a/bin/varnishtest/tests/r00972.vtc b/bin/varnishtest/tests/r00972.vtc
new file mode 100644
index 0000000..68a78dd
--- /dev/null
+++ b/bin/varnishtest/tests/r00972.vtc
@@ -0,0 +1,20 @@
+varnishtest "Test conditional delivery and do_stream"
+
+server s1 {
+	rxreq
+	txresp -hdr "ETag: foo" -body "11111\n"
+} -start
+
+varnish v1 -vcl+backend {
+	sub vcl_fetch {
+		set beresp.do_stream = true;
+	}
+} -start
+
+client c1 {
+	txreq -hdr "If-None-Match: foo"
+	rxresp
+	expect resp.status == 304
+	expect resp.http.etag == "foo"
+	expect resp.bodylen == 0
+}  -run
