[master] 4954ed3 Try to push our code into compliance with RFC7230 section 3.3.3
Poul-Henning Kamp
phk at FreeBSD.org
Tue Sep 15 15:02:15 CEST 2015
commit 4954ed3b6183bdf712324506fe7bc6074b20c0fe
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Tue Sep 15 13:01:55 2015 +0000
Try to push our code into compliance with RFC7230 section 3.3.3
diff --git a/bin/varnishd/cache/cache_esi_deliver.c b/bin/varnishd/cache/cache_esi_deliver.c
index c5d3a44..d79cde2 100644
--- a/bin/varnishd/cache/cache_esi_deliver.c
+++ b/bin/varnishd/cache/cache_esi_deliver.c
@@ -238,6 +238,7 @@ VDP_ESI(struct req *req, enum vdp_action act, void **priv,
ecx->preq = req;
*priv = ecx;
RFC2616_Weaken_Etag(req->resp);
+ req->res_mode |= RES_ESI;
if (req->resp_len != 0)
req->resp_len = -1;
return (0);
diff --git a/bin/varnishd/cache/cache_gzip.c b/bin/varnishd/cache/cache_gzip.c
index 7b08f3e..aa516bf 100644
--- a/bin/varnishd/cache/cache_gzip.c
+++ b/bin/varnishd/cache/cache_gzip.c
@@ -299,6 +299,8 @@ VDP_gunzip(struct req *req, enum vdp_action act, void **priv,
(void)VGZ_Destroy(&vg);
return (-1);
}
+
+ req->res_mode |= RES_GUNZIP;
VGZ_Obuf(vg, vg->m_buf, vg->m_sz);
*priv = vg;
diff --git a/bin/varnishd/cache/cache_priv.h b/bin/varnishd/cache/cache_priv.h
index 8fa4a9a..7d69cfa 100644
--- a/bin/varnishd/cache/cache_priv.h
+++ b/bin/varnishd/cache/cache_priv.h
@@ -36,7 +36,7 @@
* or may not, be talking a "real" HTTP protocol itself.
*/
-typedef void vtr_deliver_f (struct req *, struct busyobj *, int wantbody);
+typedef void vtr_deliver_f (struct req *, struct busyobj *, int sendbody);
struct transport {
unsigned magic;
diff --git a/bin/varnishd/cache/cache_range.c b/bin/varnishd/cache/cache_range.c
index 4011e95..6c053fc 100644
--- a/bin/varnishd/cache/cache_range.c
+++ b/bin/varnishd/cache/cache_range.c
@@ -188,7 +188,6 @@ VRG_dorange(struct req *req, const char *r)
err = vrg_dorange(req, r);
if (err != NULL) {
VSLb(req->vsl, SLT_Debug, "RANGE_FAIL %s", err);
- http_Unset(req->resp, H_Content_Length);
if (req->resp_len >= 0)
http_PrintfHeader(req->resp,
"Content-Range: bytes */%jd",
diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c
index 92cb781..abd6685 100644
--- a/bin/varnishd/cache/cache_req_fsm.c
+++ b/bin/varnishd/cache/cache_req_fsm.c
@@ -52,54 +52,60 @@ cnt_vdp(struct req *req, struct busyobj *bo)
{
const char *r;
uint16_t status;
- int wantbody;
+ int sendbody;
+ intmax_t resp_len;
CHECK_OBJ_NOTNULL(req->transport, TRANSPORT_MAGIC);
+
+ resp_len = http_GetContentLength(req->resp);
+ if (bo != NULL)
+ req->resp_len = resp_len;
+ else
+ req->resp_len = ObjGetLen(req->wrk, req->objcore);
+
req->res_mode = 0;
- wantbody = 1;
+
+ /* RFC 7230, 3.3.3 */
status = http_GetStatus(req->resp);
if (!strcmp(req->http0->hd[HTTP_HDR_METHOD].b, "HEAD")) {
- wantbody = 0;
- } else if (status < 200 || status == 204) {
+ if (req->objcore->flags & OC_F_PASS)
+ sendbody = -1;
+ else
+ sendbody = 0;
+ } else if (status < 200 || status == 204 || status == 304) {
req->resp_len = 0;
- http_Unset(req->resp, H_Content_Length);
- wantbody = 0;
- } else if (status == 304) {
- http_Unset(req->resp, H_Content_Length);
- wantbody = 0;
- } else if (bo != NULL)
- req->resp_len = http_GetContentLength(req->resp);
- else
- req->resp_len = ObjGetLen(req->wrk, req->objcore);
+ sendbody = 0;
+ } else
+ sendbody = 1;
- /*
- * Determine ESI status first. Not dependent on wantbody, because
- * we want ESI to supress C-L in HEAD too.
- */
- if (!req->disable_esi && req->resp_len != 0 && wantbody &&
- ObjGetattr(req->wrk, req->objcore, OA_ESIDATA, NULL) != NULL) {
- req->res_mode |= RES_ESI;
+ if (!req->disable_esi && req->resp_len != 0 &&
+ ObjGetattr(req->wrk, req->objcore, OA_ESIDATA, NULL) != NULL)
VDP_push(req, VDP_ESI, NULL, 0);
- }
if (cache_param->http_gzip_support &&
ObjCheckFlag(req->wrk, req->objcore, OF_GZIPED) &&
- !RFC2616_Req_Gzip(req->http)) {
- req->res_mode |= RES_GUNZIP;
+ !RFC2616_Req_Gzip(req->http))
VDP_push(req, VDP_gunzip, NULL, 1);
- }
- /*
- * Range comes after the others and pushes on bottom because
- * it can (maybe) generate a correct C-L header.
- */
if (cache_param->http_range_support && http_IsStatus(req->resp, 200)) {
http_SetHeader(req->resp, "Accept-Ranges: bytes");
- if (wantbody && http_GetHdr(req->http, H_Range, &r))
+ if (sendbody && http_GetHdr(req->http, H_Range, &r))
VRG_dorange(req, r);
}
- req->transport->deliver(req, bo, wantbody);
+ if (sendbody < 0) {
+ /* Don't touch pass+HEAD C-L */
+ sendbody = 0;
+ } else if (resp_len >= 0 && resp_len == req->resp_len) {
+ /* Reuse C-L header */
+ } else {
+ http_Unset(req->resp, H_Content_Length);
+ if (req->resp_len >= 0 && sendbody)
+ http_PrintfHeader(req->resp,
+ "Content-Length: %jd", req->resp_len);
+ }
+
+ req->transport->deliver(req, bo, sendbody);
}
/*--------------------------------------------------------------------
@@ -254,10 +260,12 @@ cnt_synth(struct worker *wrk, struct req *req)
VCL_synth_method(req->vcl, wrk, req, NULL, synth_body);
- http_Unset(h, H_Content_Length);
-
AZ(VSB_finish(synth_body));
+ http_Unset(h, H_Content_Length);
+ http_PrintfHeader(req->resp, "Content-Length: %zd",
+ VSB_len(synth_body));
+
/* Discard any lingering request body before delivery */
(void)VRB_Ignore(req);
diff --git a/bin/varnishd/http1/cache_http1_deliver.c b/bin/varnishd/http1/cache_http1_deliver.c
index fdd176a..997d28b 100644
--- a/bin/varnishd/http1/cache_http1_deliver.c
+++ b/bin/varnishd/http1/cache_http1_deliver.c
@@ -79,7 +79,7 @@ v1d_error(struct req *req, const char *msg)
*/
void __match_proto__(vtr_deliver_f)
-V1D_Deliver(struct req *req, struct busyobj *bo, int wantbody)
+V1D_Deliver(struct req *req, struct busyobj *bo, int sendbody)
{
enum objiter_status ois;
@@ -87,19 +87,10 @@ V1D_Deliver(struct req *req, struct busyobj *bo, int wantbody)
CHECK_OBJ_ORNULL(bo, BUSYOBJ_MAGIC);
CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
- if (wantbody) {
- http_Unset(req->resp, H_Content_Length);
- if (req->resp_len >= 0)
- http_PrintfHeader(req->resp,
- "Content-Length: %jd", req->resp_len);
- }
-
- if (req->resp_len == 0)
- wantbody = 0;
- else if (http_GetHdr(req->resp, H_Content_Length, NULL))
- req->res_mode |= RES_LEN;
- else if (wantbody) {
- if (req->http->protover == 11) {
+ if (sendbody) {
+ if (http_GetHdr(req->resp, H_Content_Length, NULL))
+ req->res_mode |= RES_LEN;
+ else if (req->http->protover == 11) {
req->res_mode |= RES_CHUNKED;
http_SetHeader(req->resp, "Transfer-Encoding: chunked");
} else {
@@ -118,7 +109,8 @@ V1D_Deliver(struct req *req, struct busyobj *bo, int wantbody)
} else if (!http_GetHdr(req->resp, H_Connection, NULL))
http_SetHeader(req->resp, "Connection: keep-alive");
- VDP_push(req, v1d_bytes, NULL, 1);
+ if (sendbody && req->resp_len != 0)
+ VDP_push(req, v1d_bytes, NULL, 1);
V1L_Reserve(req->wrk, req->ws, &req->sp->fd, req->vsl, req->t_prev);
@@ -132,7 +124,7 @@ V1D_Deliver(struct req *req, struct busyobj *bo, int wantbody)
(void)V1L_Flush(req->wrk);
ois = OIS_DONE;
- if (wantbody) {
+ if (sendbody && req->resp_len != 0) {
if (req->res_mode & RES_CHUNKED)
V1L_Chunked(req->wrk);
ois = VDP_DeliverObj(req);
diff --git a/bin/varnishd/http1/cache_http1_proto.c b/bin/varnishd/http1/cache_http1_proto.c
index 8fa7e9e..8d08278 100644
--- a/bin/varnishd/http1/cache_http1_proto.c
+++ b/bin/varnishd/http1/cache_http1_proto.c
@@ -272,7 +272,7 @@ http1_splitline(struct http *hp, struct http_conn *htc, const int *hf)
/*--------------------------------------------------------------------*/
static enum body_status
-http1_body_status(struct http *hp, struct http_conn *htc)
+http1_body_status(const struct http *hp, struct http_conn *htc)
{
ssize_t cl;
const char *b;
More information about the varnish-commit
mailing list