[4.0] 22b8488 Cut the thicket for setting a HTTP response's first line down to just one function which does what you'd expect.

Poul-Henning Kamp phk at FreeBSD.org
Tue Jun 24 11:31:54 CEST 2014


commit 22b8488592d5b76af6ac0636e070861be3e892d9
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Wed Jun 4 07:42:25 2014 +0000

    Cut the thicket for setting a HTTP response's first line down to just
    one function which does what you'd expect.
    
    Start allowing internal VCL use of *resp.status > 999.  The idea
    is that we ignore the higher bits but it still has to end up >=
    100, so 10404 becomes 404 and 20099 is illegal.   (This change
    is not yet complete it will panic if you use it yet.)
    
    More http->failed stuff.

diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index 1c2732b..2429ccd 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -987,14 +987,11 @@ struct http *HTTP_create(void *p, uint16_t nhttp);
 const char *http_StatusMessage(unsigned);
 unsigned http_EstimateWS(const struct http *fm, unsigned how, uint16_t *nhd);
 void HTTP_Init(void);
-void http_SetResp(struct http *to, const char *proto, uint16_t status,
+void http_PutResponse(struct http *to, const char *proto, uint16_t status,
     const char *response);
 void http_FilterReq(struct http *to, const struct http *fm, unsigned how);
 void http_FilterResp(const struct http *fm, struct http *to, unsigned how);
-void http_PutProtocol(struct http *to, const char *protocol);
-void http_PutStatus(struct http *to, uint16_t status);
 void http_ForceHeader(struct http *to, const char *hdr, const char *val);
-void http_PutResponse(struct http *to, const char *response);
 void http_PrintfHeader(struct http *to, const char *fmt, ...)
     __printflike(2, 3);
 void http_SetHeader(struct http *to, const char *hdr);
diff --git a/bin/varnishd/cache/cache_fetch.c b/bin/varnishd/cache/cache_fetch.c
index 7ad709d..450560c 100644
--- a/bin/varnishd/cache/cache_fetch.c
+++ b/bin/varnishd/cache/cache_fetch.c
@@ -686,7 +686,7 @@ 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_SetResp(bo->beresp, "HTTP/1.1", 503, "Backend fetch failed");
+	http_PutResponse(bo->beresp, "HTTP/1.1", 503, "Backend fetch failed");
 	VTIM_format(now, time_str);
 	http_PrintfHeader(bo->beresp, "Date: %s", time_str);
 	http_SetHeader(bo->beresp, "Server: Varnish");
diff --git a/bin/varnishd/cache/cache_http.c b/bin/varnishd/cache/cache_http.c
index 032ac79..d4296cd 100644
--- a/bin/varnishd/cache/cache_http.c
+++ b/bin/varnishd/cache/cache_http.c
@@ -120,11 +120,12 @@ http_StatusMessage(unsigned status)
 {
 	struct http_msg *mp;
 
-	assert(status >= 100 && status <= 999);
+	status %= 1000;
+	assert(status >= 100);
 	for (mp = http_msg; mp->nbr != 0 && mp->nbr <= status; mp++)
 		if (mp->nbr == status)
 			return (mp->txt);
-	return ("Unknown Error");
+	return ("Unknown HTTP Status");
 }
 
 /*--------------------------------------------------------------------*/
@@ -527,6 +528,25 @@ http_GetReq(const struct http *hp)
 
 /*--------------------------------------------------------------------*/
 
+static void
+http_PutField(struct http *to, int field, const char *string)
+{
+	char *p;
+
+	CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
+	p = WS_Copy(to->ws, string, -1);
+	if (p == NULL) {
+		http_fail(to);
+		VSLb(to->vsl, SLT_LostHeader, "%s", string);
+		return;
+	}
+	to->hd[field].b = p;
+	to->hd[field].e = strchr(p, '\0');
+	to->hdf[field] = 0;
+	http_VSLH(to, field);
+}
+/*--------------------------------------------------------------------*/
+
 void
 http_SetH(const struct http *to, unsigned n, const char *fm)
 {
@@ -547,14 +567,24 @@ http_ForceGet(const struct http *to)
 }
 
 void
-http_SetResp(struct http *to, const char *proto, uint16_t status,
+http_PutResponse(struct http *to, const char *proto, uint16_t status,
     const char *response)
 {
+	char buf[4];
 
 	CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
 	http_SetH(to, HTTP_HDR_PROTO, proto);
-	assert(status >= 100 && status <= 999);
-	http_PutStatus(to, status);
+	/*
+	 * We allow people to use top digits for internal VCL
+	 * signalling, strip them here.
+	 */
+	status %= 1000;
+	assert(status >= 100);
+	to->status = status;
+	bprintf(buf, "%03d", status % 1000);
+	http_PutField(to, HTTP_HDR_STATUS, buf);
+	if (response == NULL)
+		response = http_StatusMessage(status);
 	http_SetH(to, HTTP_HDR_RESPONSE, response);
 }
 
@@ -757,55 +787,6 @@ http_ForceHeader(struct http *to, const char *hdr, const char *val)
 	http_PrintfHeader(to, "%s %s", hdr + 1, val);
 }
 
-/*--------------------------------------------------------------------*/
-
-static void
-http_PutField(struct http *to, int field, const char *string)
-{
-	char *p;
-
-	CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
-	p = WS_Copy(to->ws, string, -1);
-	if (p == NULL) {
-		http_fail(to);
-		VSLb(to->vsl, SLT_LostHeader, "%s", string);
-		return;
-	}
-	to->hd[field].b = p;
-	to->hd[field].e = strchr(p, '\0');
-	to->hdf[field] = 0;
-	http_VSLH(to, field);
-}
-
-void
-http_PutProtocol(struct http *to, const char *protocol)
-{
-
-	AN(protocol);
-	http_PutField(to, HTTP_HDR_PROTO, protocol);
-	Tcheck(to->hd[HTTP_HDR_PROTO]);
-}
-
-void
-http_PutStatus(struct http *to, uint16_t status)
-{
-	char buf[4];
-
-	assert(status >= 100 && status <= 999);
-	to->status = status;
-	bprintf(buf, "%03d", status % 1000);
-	http_PutField(to, HTTP_HDR_STATUS, buf);
-}
-
-void
-http_PutResponse(struct http *to, const char *response)
-{
-
-	AN(response);
-	http_PutField(to, HTTP_HDR_RESPONSE, response);
-	Tcheck(to->hd[HTTP_HDR_RESPONSE]);
-}
-
 void
 http_PrintfHeader(struct http *to, const char *fmt, ...)
 {
@@ -822,7 +803,7 @@ http_PrintfHeader(struct http *to, const char *fmt, ...)
 		VSLb(to->vsl, SLT_LostHeader, "%s", to->ws->f);
 		WS_Release(to->ws, 0);
 		return;
-	} 
+	}
 	to->hd[to->nhd].b = to->ws->f;
 	to->hd[to->nhd].e = to->ws->f + n;
 	to->hdf[to->nhd] = 0;
diff --git a/bin/varnishd/cache/cache_http1_deliver.c b/bin/varnishd/cache/cache_http1_deliver.c
index 0b0e138..06b4a32 100644
--- a/bin/varnishd/cache/cache_http1_deliver.c
+++ b/bin/varnishd/cache/cache_http1_deliver.c
@@ -154,7 +154,7 @@ v1d_dorange(struct req *req, const char *r)
 	if (req->res_mode & RES_LEN)
 		http_PrintfHeader(req->resp, "Content-Length: %jd",
 		    (intmax_t)(1 + high - low));
-	http_SetResp(req->resp, "HTTP/1.1", 206, "Partial Content");
+	http_PutResponse(req->resp, "HTTP/1.1", 206, NULL);
 
 	req->range_off = 0;
 	req->range_low = low;
diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c
index 0eed42b..d14f398 100644
--- a/bin/varnishd/cache/cache_req_fsm.c
+++ b/bin/varnishd/cache/cache_req_fsm.c
@@ -149,7 +149,7 @@ cnt_deliver(struct worker *wrk, struct req *req)
 	    && req->esi_level == 0
 	    && http_GetStatus(req->obj->http) == 200
 	    && req->http->conds && RFC2616_Do_Cond(req))
-		http_SetResp(req->resp, "HTTP/1.1", 304, "Not Modified");
+		http_PutResponse(req->resp, "HTTP/1.1", 304, NULL);
 
 	V1D_Deliver(req);
 	VSLb_ts_req(req, "Resp", W_TIM_real(wrk));
@@ -209,17 +209,12 @@ cnt_synth(struct worker *wrk, struct req *req)
 
 	HTTP_Setup(req->resp, req->ws, req->vsl, SLT_RespMethod);
 	h = req->resp;
-	http_PutProtocol(h, "HTTP/1.1");
-	http_PutStatus(h, req->err_code);
 	VTIM_format(now, date);
 	http_PrintfHeader(h, "Date: %s", date);
 	http_SetHeader(h, "Server: Varnish");
 	http_PrintfHeader(req->resp,
 	    "X-Varnish: %u", req->vsl->wid & VSL_IDENTMASK);
-	if (req->err_reason != NULL)
-		http_PutResponse(h, req->err_reason);
-	else
-		http_PutResponse(h, http_StatusMessage(req->err_code));
+	http_PutResponse(h, "HTTP/1.1", req->err_code, req->err_reason);
 
 	AZ(req->synth_body);
 	req->synth_body = VSB_new_auto();
diff --git a/bin/varnishd/cache/cache_vrt_var.c b/bin/varnishd/cache/cache_vrt_var.c
index 65c72db..d2e6647 100644
--- a/bin/varnishd/cache/cache_vrt_var.c
+++ b/bin/varnishd/cache/cache_vrt_var.c
@@ -48,19 +48,20 @@ static char vrt_hostname[255] = "";
 /*--------------------------------------------------------------------*/
 
 static void
-vrt_do_string(const struct http *hp, int fld,
+vrt_do_string(struct http *hp, int fld,
     const char *err, const char *p, va_list ap)
 {
 	const char *b;
 
-	AN(hp);
+	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
+
 	b = VRT_String(hp->ws, NULL, p, ap);
 	if (b == NULL || *b == '\0') {
 		VSLb(hp->vsl, SLT_LostHeader, "%s", err);
+		hp->failed = 1;
 	} else {
 		http_SetH(hp, fld, b);
 	}
-	va_end(ap);
 }
 
 #define VRT_HDR_L(obj, hdr, fld)					\
@@ -95,8 +96,15 @@ VRT_l_##obj##_status(const struct vrt_ctx *ctx, long num)		\
 									\
 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);				\
 	CHECK_OBJ_NOTNULL(ctx->http_##obj, HTTP_MAGIC);			\
-	assert(num >= 100 && num <= 999);				\
-	ctx->http_##obj->status = (uint16_t)num;			\
+	if (num > 65535) {						\
+		VSLb(ctx->vsl, SLT_VCL_Error, "%s.status > 65535", #obj); \
+		ctx->http_##obj->failed = 1;				\
+	} else if ((num % 1000) < 100) {				\
+		VSLb(ctx->vsl, SLT_VCL_Error, "illegal %s.status (..0##)", \
+		    #obj);						\
+		ctx->http_##obj->failed = 1;				\
+	} else								\
+		ctx->http_##obj->status = (uint16_t)num;		\
 }
 
 #define VRT_STATUS_R(obj)						\



More information about the varnish-commit mailing list