[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