[master] e99e8fb Always set the reason headerfield when the status field is set, to keep them in sync. If you want a custom reason field, set status first, then reason.

Poul-Henning Kamp phk at FreeBSD.org
Tue Jun 10 10:34:06 CEST 2014


commit e99e8fbaa85aafa36abaa0aa9f508e98fd93dfc8
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Tue Jun 10 08:31:16 2014 +0000

    Always set the reason headerfield when the status field is set, to
    keep them in sync.  If you want a custom reason field, set status
    first, then reason.
    
    With this in place, HTTP1_Write() doesn't need to worry about them
    being OK, and we can polish that code a fair bit.
    
    Turn a couple of boolean arguments into more readable magics.

diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index a79b224..38e597b 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -857,6 +857,8 @@ void HTTP1_Session(struct worker *, struct req *);
 int HTTP1_DiscardReqBody(struct req *req);
 int HTTP1_CacheReqBody(struct req *req, ssize_t maxsize);
 int HTTP1_IterateReqBody(struct req *req, req_body_iter_f *func, void *priv);
+extern const int HTTP1_Req[3];
+extern const int HTTP1_Resp[3];
 
 /* cache_http1_deliver.c */
 unsigned V1D_FlushReleaseAcct(struct req *req);
@@ -1030,7 +1032,7 @@ ssize_t HTTP1_Read(struct http_conn *htc, void *d, size_t len);
 enum htc_status_e HTTP1_Complete(struct http_conn *htc);
 uint16_t HTTP1_DissectRequest(struct req *);
 uint16_t HTTP1_DissectResponse(struct http *sp, const struct http_conn *htc);
-unsigned HTTP1_Write(const struct worker *w, const struct http *hp, int resp);
+unsigned HTTP1_Write(const struct worker *w, const struct http *hp, const int*);
 
 #define HTTPH(a, b, c) extern char b[];
 #include "tbl/http_headers.h"
diff --git a/bin/varnishd/cache/cache_http.c b/bin/varnishd/cache/cache_http.c
index 8313007..159751b 100644
--- a/bin/varnishd/cache/cache_http.c
+++ b/bin/varnishd/cache/cache_http.c
@@ -552,7 +552,9 @@ http_GetStatus(const struct http *hp)
 	return (hp->status);
 }
 
-/*--------------------------------------------------------------------*/
+/*--------------------------------------------------------------------
+ * Setting the status will also set the Reason appropriately
+ */
 
 void
 http_SetStatus(struct http *to, uint16_t status)
@@ -569,6 +571,7 @@ http_SetStatus(struct http *to, uint16_t status)
 	assert(status >= 100);
 	bprintf(buf, "%03d", status);
 	http_PutField(to, HTTP_HDR_STATUS, buf);
+	http_SetH(to, HTTP_HDR_REASON, http_Status2Reason(status));
 }
 
 /*--------------------------------------------------------------------*/
diff --git a/bin/varnishd/cache/cache_http1_deliver.c b/bin/varnishd/cache/cache_http1_deliver.c
index 06b4a32..8778303 100644
--- a/bin/varnishd/cache/cache_http1_deliver.c
+++ b/bin/varnishd/cache/cache_http1_deliver.c
@@ -322,7 +322,8 @@ V1D_Deliver(struct req *req)
 	 * Send HTTP protocol header, unless interior ESI object
 	 */
 	if (!(req->res_mode & RES_ESI_CHILD))
-		req->resp_hdrbytes += HTTP1_Write(req->wrk, req->resp, 1);
+		req->resp_hdrbytes +=
+		    HTTP1_Write(req->wrk, req->resp, HTTP1_Resp);
 
 	if (req->res_mode & RES_CHUNKED)
 		WRW_Chunked(req->wrk);
@@ -429,7 +430,8 @@ V1D_Deliver_Synth(struct req *req)
 	 * Send HTTP protocol header, unless interior ESI object
 	 */
 	if (!(req->res_mode & RES_ESI_CHILD))
-		req->resp_hdrbytes += HTTP1_Write(req->wrk, req->resp, 1);
+		req->resp_hdrbytes +=
+		    HTTP1_Write(req->wrk, req->resp, HTTP1_Resp);
 
 	if (req->res_mode & RES_CHUNKED)
 		WRW_Chunked(req->wrk);
diff --git a/bin/varnishd/cache/cache_http1_fetch.c b/bin/varnishd/cache/cache_http1_fetch.c
index 11c712e..1c3ef53 100644
--- a/bin/varnishd/cache/cache_http1_fetch.c
+++ b/bin/varnishd/cache/cache_http1_fetch.c
@@ -327,7 +327,7 @@ V1F_fetch_hdr(struct worker *wrk, struct busyobj *bo, struct req *req)
 
 	(void)VTCP_blocking(vc->fd);	/* XXX: we should timeout instead */
 	WRW_Reserve(wrk, &vc->fd, bo->vsl, bo->t_prev);
-	hdrbytes = HTTP1_Write(wrk, hp, 0);
+	hdrbytes = HTTP1_Write(wrk, hp, HTTP1_Req);
 
 	/* Deal with any message-body the request might (still) have */
 	i = 0;
diff --git a/bin/varnishd/cache/cache_http1_proto.c b/bin/varnishd/cache/cache_http1_proto.c
index 7316f0b..7f7852c 100644
--- a/bin/varnishd/cache/cache_http1_proto.c
+++ b/bin/varnishd/cache/cache_http1_proto.c
@@ -49,6 +49,14 @@
 
 #include "vct.h"
 
+const int HTTP1_Req[3] = {
+	HTTP_HDR_METHOD, HTTP_HDR_URL, HTTP_HDR_PROTO
+};
+
+const int HTTP1_Resp[3] = {
+	HTTP_HDR_PROTO, HTTP_HDR_STATUS, HTTP_HDR_REASON
+};
+
 /*--------------------------------------------------------------------*/
 
 void
@@ -294,55 +302,46 @@ htc_dissect_hdrs(struct http *hp, char *p, const struct http_conn *htc)
  */
 
 static uint16_t
-htc_splitline(struct http *hp, const struct http_conn *htc, int req)
+htc_splitline(struct http *hp, const struct http_conn *htc, const int *hf)
 {
 	char *p;
-	int h1, h2, h3;
 
+	assert(hf == HTTP1_Req || hf == HTTP1_Resp);
 	CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
 	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
 	Tcheck(htc->rxbuf);
 
-	if (req) {
-		h1 = HTTP_HDR_METHOD;
-		h2 = HTTP_HDR_URL;
-		h3 = HTTP_HDR_PROTO;
-	} else {
-		h1 = HTTP_HDR_PROTO;
-		h2 = HTTP_HDR_STATUS;
-		h3 = HTTP_HDR_REASON;
-	}
-	AZ(hp->hd[h1].b);
-	AZ(hp->hd[h2].b);
-	AZ(hp->hd[h3].b);
+	AZ(hp->hd[hf[0]].b);
+	AZ(hp->hd[hf[1]].b);
+	AZ(hp->hd[hf[2]].b);
 
 	/* Skip leading LWS */
 	for (p = htc->rxbuf.b ; vct_islws(*p); p++)
 		continue;
-	hp->hd[h1].b = p;
+	hp->hd[hf[0]].b = p;
 
 	/* First field cannot contain SP or CTL */
 	for (; !vct_issp(*p); p++) {
 		if (vct_isctl(*p))
 			return (400);
 	}
-	hp->hd[h1].e = p;
-	assert(Tlen(hp->hd[h1]));
+	hp->hd[hf[0]].e = p;
+	assert(Tlen(hp->hd[hf[0]]));
 
 	/* Skip SP */
 	for (; vct_issp(*p); p++) {
 		if (vct_isctl(*p))
 			return (400);
 	}
-	hp->hd[h2].b = p;
+	hp->hd[hf[1]].b = p;
 
 	/* Second field cannot contain LWS or CTL */
 	for (; !vct_islws(*p); p++) {
 		if (vct_isctl(*p))
 			return (400);
 	}
-	hp->hd[h2].e = p;
-	if (!Tlen(hp->hd[h2]))
+	hp->hd[hf[1]].e = p;
+	if (!Tlen(hp->hd[hf[1]]))
 		return (400);
 
 	/* Skip SP */
@@ -350,23 +349,23 @@ htc_splitline(struct http *hp, const struct http_conn *htc, int req)
 		if (vct_isctl(*p))
 			return (400);
 	}
-	hp->hd[h3].b = p;
+	hp->hd[hf[2]].b = p;
 
 	/* Third field is optional and cannot contain CTL except TAB */
 	for (; !vct_iscrlf(p); p++) {
 		if (vct_isctl(*p) && !vct_issp(*p)) {
-			hp->hd[h3].b = NULL;
+			hp->hd[hf[2]].b = NULL;
 			return (400);
 		}
 	}
-	hp->hd[h3].e = p;
+	hp->hd[hf[2]].e = p;
 
 	/* Skip CRLF */
 	p += vct_skipcrlf(p);
 
-	*hp->hd[h1].e = '\0';
-	*hp->hd[h2].e = '\0';
-	*hp->hd[h3].e = '\0';
+	*hp->hd[hf[0]].e = '\0';
+	*hp->hd[hf[1]].e = '\0';
+	*hp->hd[hf[2]].e = '\0';
 
 	return (htc_dissect_hdrs(hp, p, htc));
 }
@@ -426,7 +425,7 @@ HTTP1_DissectRequest(struct req *req)
 	hp = req->http;
 	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
 
-	retval = htc_splitline(hp, htc, 1);
+	retval = htc_splitline(hp, htc, HTTP1_Req);
 	if (retval != 0) {
 		VSLbt(req->vsl, SLT_HttpGarbage, htc->rxbuf);
 		return (retval);
@@ -465,7 +464,7 @@ HTTP1_DissectResponse(struct http *hp, const struct http_conn *htc)
 	CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
 	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
 
-	if (htc_splitline(hp, htc, 0))
+	if (htc_splitline(hp, htc, HTTP1_Resp))
 		retval = 503;
 
 	if (retval == 0) {
@@ -495,6 +494,7 @@ HTTP1_DissectResponse(struct http *hp, const struct http_conn *htc)
 		assert(retval == 503);
 		hp->status = retval;
 		http_SetH(hp, HTTP_HDR_STATUS, "503");
+		http_SetH(hp, HTTP_HDR_REASON, http_Status2Reason(retval));
 	}
 
 	if (hp->hd[HTTP_HDR_REASON].b == NULL ||
@@ -507,36 +507,20 @@ HTTP1_DissectResponse(struct http *hp, const struct http_conn *htc)
 /*--------------------------------------------------------------------*/
 
 unsigned
-HTTP1_Write(const struct worker *w, const struct http *hp, int resp)
+HTTP1_Write(const struct worker *w, const struct http *hp, const int *hf)
 {
 	unsigned u, l;
 
-	if (resp) {
-		l = WRW_WriteH(w, &hp->hd[HTTP_HDR_PROTO], " ");
-
-		hp->hd[HTTP_HDR_STATUS].b = WS_Alloc(hp->ws, 4);
-		AN(hp->hd[HTTP_HDR_STATUS].b);
+	assert(hf == HTTP1_Req || hf == HTTP1_Resp);
+	AN(hp->hd[hf[0]].b);
+	AN(hp->hd[hf[1]].b);
+	AN(hp->hd[hf[2]].b);
+	l = WRW_WriteH(w, &hp->hd[hf[0]], " ");
+	l += WRW_WriteH(w, &hp->hd[hf[1]], " ");
+	l += WRW_WriteH(w, &hp->hd[hf[2]], "\r\n");
 
-		assert(hp->status >= 100 && hp->status <= 999);
-		sprintf(hp->hd[HTTP_HDR_STATUS].b, "%3d", hp->status);
-		hp->hd[HTTP_HDR_STATUS].e = hp->hd[HTTP_HDR_STATUS].b + 3;
-
-		l += WRW_WriteH(w, &hp->hd[HTTP_HDR_STATUS], " ");
-
-		l += WRW_WriteH(w, &hp->hd[HTTP_HDR_REASON], "\r\n");
-	} else {
-		AN(hp->hd[HTTP_HDR_URL].b);
-		l = WRW_WriteH(w, &hp->hd[HTTP_HDR_METHOD], " ");
-		l += WRW_WriteH(w, &hp->hd[HTTP_HDR_URL], " ");
-		l += WRW_WriteH(w, &hp->hd[HTTP_HDR_PROTO], "\r\n");
-	}
-	for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
-		if (hp->hd[u].b == NULL)
-			continue;
-		AN(hp->hd[u].b);
-		AN(hp->hd[u].e);
+	for (u = HTTP_HDR_FIRST; u < hp->nhd; u++)
 		l += WRW_WriteH(w, &hp->hd[u], "\r\n");
-	}
 	l += WRW_Write(w, "\r\n", -1);
 	return (l);
 }
diff --git a/bin/varnishd/cache/cache_pipe.c b/bin/varnishd/cache/cache_pipe.c
index bb666a1..27ea964 100644
--- a/bin/varnishd/cache/cache_pipe.c
+++ b/bin/varnishd/cache/cache_pipe.c
@@ -124,7 +124,7 @@ PipeRequest(struct req *req, struct busyobj *bo)
 	(void)VTCP_blocking(vc->fd);
 
 	WRW_Reserve(wrk, &vc->fd, bo->vsl, req->t_req);
-	hdrbytes = HTTP1_Write(wrk, bo->bereq, 0);
+	hdrbytes = HTTP1_Write(wrk, bo->bereq, HTTP1_Req);
 
 	if (req->htc->pipeline.b != NULL)
 		(void)WRW_Write(wrk, req->htc->pipeline.b,



More information about the varnish-commit mailing list