Commit 0ea83286 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Further split the "how" from the "what" of response delivery.

Here be dragons.   For instance that if a HEAD is passed, we should
let the Content-Length: unmolested through, whereas normally C-L is a
property of the protocol delivery of the HTTP response.
parent 1764f13a
......@@ -306,8 +306,7 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo)
if (bo->htc.body_status == BS_NONE)
bo->do_stream = 0;
l = http_EstimateWS(bo->beresp,
bo->uncacheable ? HTTPH_R_PASS : HTTPH_A_INS, &nhttp);
l = 0;
/* Create Vary instructions */
if (!(bo->fetch_objcore->flags & OC_F_PRIVATE)) {
......@@ -331,18 +330,15 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo)
AZ(vary);
}
l += http_EstimateWS(bo->beresp,
bo->uncacheable ? HTTPH_R_PASS : HTTPH_A_INS, &nhttp);
if (bo->uncacheable)
bo->fetch_objcore->flags |= OC_F_PASS;
if (bo->exp.ttl < cache_param->shortlived || bo->uncacheable == 1)
bo->storage_hint = TRANSIENT_STORAGE;
/*
* Space for producing a Content-Length: header including padding
* A billion gigabytes is enough for anybody.
*/
l += strlen("Content-Length: XxxXxxXxxXxxXxxXxx") + sizeof(void *);
AZ(bo->stats);
bo->stats = &wrk->stats;
AN(bo->fetch_objcore);
......
......@@ -311,7 +311,6 @@ V1F_fetch_body(struct worker *wrk, struct busyobj *bo)
{
int cls;
struct storage *st;
int mklen;
ssize_t cl;
struct http_conn *htc;
struct object *obj;
......@@ -342,10 +341,8 @@ V1F_fetch_body(struct worker *wrk, struct busyobj *bo)
cls = bo->should_close;
switch (htc->body_status) {
case BS_NONE:
mklen = 0;
break;
case BS_ZERO:
mklen = 1;
break;
case BS_LENGTH:
cl = vbf_fetch_number(bo->h_content_length, 10);
......@@ -353,7 +350,6 @@ V1F_fetch_body(struct worker *wrk, struct busyobj *bo)
bo->vfp->begin(bo, cl);
if (bo->state == BOS_FETCHING && cl > 0)
cls |= vbf_fetch_straight(bo, htc, cl);
mklen = 1;
if (bo->vfp->end(bo))
assert(bo->state == BOS_FAILED);
break;
......@@ -361,7 +357,6 @@ V1F_fetch_body(struct worker *wrk, struct busyobj *bo)
bo->vfp->begin(bo, cl > 0 ? cl : 0);
if (bo->state == BOS_FETCHING)
cls |= vbf_fetch_chunked(bo, htc);
mklen = 1;
if (bo->vfp->end(bo))
assert(bo->state == BOS_FAILED);
break;
......@@ -369,17 +364,14 @@ V1F_fetch_body(struct worker *wrk, struct busyobj *bo)
bo->vfp->begin(bo, cl > 0 ? cl : 0);
if (bo->state == BOS_FETCHING)
vbf_fetch_eof(bo, htc);
mklen = 1;
cls = 1;
if (bo->vfp->end(bo))
assert(bo->state == BOS_FAILED);
break;
case BS_ERROR:
cls |= VFP_Error(bo, "error incompatible Transfer-Encoding");
mklen = 0;
break;
default:
mklen = 0;
INCOMPL();
}
AZ(bo->vgz_rx);
......@@ -401,9 +393,8 @@ V1F_fetch_body(struct worker *wrk, struct busyobj *bo)
bo->vfp = NULL;
VSLb(bo->vsl, SLT_Fetch_Body, "%u(%s) cls %d mklen %d",
htc->body_status, body_status_2str(htc->body_status),
cls, mklen);
VSLb(bo->vsl, SLT_Fetch_Body, "%u(%s) cls %d",
htc->body_status, body_status_2str(htc->body_status), cls);
http_Teardown(bo->bereq);
http_Teardown(bo->beresp);
......@@ -440,12 +431,6 @@ V1F_fetch_body(struct worker *wrk, struct busyobj *bo)
else
assert(uu == obj->len);
}
if (mklen > 0) {
http_Unset(obj->http, H_Content_Length);
http_PrintfHeader(obj->http,
"Content-Length: %zd", obj->len);
}
}
bo->stats = NULL;
}
......@@ -169,45 +169,6 @@ cnt_deliver(struct worker *wrk, struct req *req)
assert(req->obj->objcore->refcnt > 0);
req->res_mode = 0;
if (!req->disable_esi && req->obj->esidata != NULL) {
/* In ESI mode, we can't know the aggregate length */
req->res_mode &= ~RES_LEN;
req->res_mode |= RES_ESI;
} else if (req->obj->objcore->busyobj == NULL) {
req->res_mode |= RES_LEN;
}
if (req->esi_level > 0) {
/* Included ESI object, always CHUNKED or EOF */
req->res_mode &= ~RES_LEN;
req->res_mode |= RES_ESI_CHILD;
}
if (cache_param->http_gzip_support && req->obj->gziped &&
!RFC2616_Req_Gzip(req->http)) {
/*
* We don't know what it uncompresses to
* XXX: we could cache that
*/
req->res_mode &= ~RES_LEN;
req->res_mode |= RES_GUNZIP;
}
if (!(req->res_mode & (RES_LEN|RES_CHUNKED|RES_EOF))) {
/* We havn't chosen yet, do so */
if (!req->wantbody) {
/* Nothing */
} else if (req->http->protover >= 11) {
req->res_mode |= RES_CHUNKED;
} else {
req->res_mode |= RES_EOF;
req->doclose = SC_TX_EOF;
}
}
VSLb(req->vsl, SLT_Debug, "RES_MODE %x", req->res_mode);
req->t_resp = W_TIM_real(wrk);
if (!(req->obj->objcore->flags & OC_F_PRIVATE)) {
if ((req->t_resp - req->obj->last_lru) >
......@@ -224,7 +185,7 @@ cnt_deliver(struct worker *wrk, struct req *req)
http_FilterResp(req->obj->http, req->resp, 0);
http_Unset(req->resp, H_Date);
VTIM_format(VTIM_real(), time_str);
VTIM_format(req->t_resp, time_str);
http_PrintfHeader(req->resp, "Date: %s", time_str);
if (req->wrk->stats.cache_hit)
......@@ -239,17 +200,15 @@ cnt_deliver(struct worker *wrk, struct req *req)
req->obj->exp.age + req->t_resp - req->obj->exp.entered);
http_SetHeader(req->resp, "Via: 1.1 varnish");
VCL_deliver_method(req->vcl, wrk, req, NULL, req->http->ws);
RES_BuildHttp(req);
while (req->obj->objcore->busyobj) {
VSLb(req->vsl, SLT_Debug, "HERE %s %d", __func__, __LINE__);
(void)usleep(10000);
}
RES_BuildHttp(req);
/* Stop the insanity before it turns "Hotel California" on us */
if (req->restarts >= cache_param->max_restarts)
......
......@@ -108,13 +108,57 @@ RES_BuildHttp(struct req *req)
CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC);
if (!(req->res_mode & RES_LEN)) {
http_Unset(req->resp, H_Content_Length);
} else if (cache_param->http_range_support) {
/* We only accept ranges if we know the length */
http_SetHeader(req->resp, "Accept-Ranges: bytes");
req->res_mode = 0;
if (!req->disable_esi && req->obj->esidata != NULL) {
/* In ESI mode, we can't know the aggregate length */
req->res_mode &= ~RES_LEN;
req->res_mode |= RES_ESI;
} else if (req->obj->objcore->busyobj == NULL) {
/* XXX: Not happy with this convoluted test */
req->res_mode |= RES_LEN;
if (!(req->obj->objcore->flags & OC_F_PASS) ||
req->obj->len != 0) {
http_Unset(req->resp, H_Content_Length);
http_PrintfHeader(req->resp,
"Content-Length: %zd", req->obj->len);
}
if (cache_param->http_range_support)
http_SetHeader(req->resp, "Accept-Ranges: bytes");
}
if (req->esi_level > 0) {
/* Included ESI object, always CHUNKED or EOF */
req->res_mode &= ~RES_LEN;
req->res_mode |= RES_ESI_CHILD;
}
if (cache_param->http_gzip_support && req->obj->gziped &&
!RFC2616_Req_Gzip(req->http)) {
/*
* We don't know what it uncompresses to
* XXX: we could cache that
*/
req->res_mode &= ~RES_LEN;
req->res_mode |= RES_GUNZIP;
}
if (!(req->res_mode & (RES_LEN|RES_CHUNKED|RES_EOF))) {
/* We havn't chosen yet, do so */
if (!req->wantbody) {
/* Nothing */
} else if (req->http->protover >= 11) {
req->res_mode |= RES_CHUNKED;
} else {
req->res_mode |= RES_EOF;
req->doclose = SC_TX_EOF;
}
}
VSLb(req->vsl, SLT_Debug, "RES_MODE %x", req->res_mode);
if (!(req->res_mode & RES_LEN))
http_Unset(req->resp, H_Content_Length);
if (req->res_mode & RES_GUNZIP)
http_Unset(req->resp, H_Content_Encoding);
......
......@@ -419,8 +419,6 @@ VRT_synth_page(const struct vrt_ctx *ctx, unsigned flags, const char *str, ...)
va_end(ap);
SMS_Finish(ctx->req->obj);
http_Unset(ctx->req->obj->http, H_Content_Length);
http_PrintfHeader(ctx->req->obj->http,
"Content-Length: %zd", ctx->req->obj->len);
}
/*--------------------------------------------------------------------*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment