Commit 4be6020b authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Split beresp.body status determination into transport protocol

dependent (is there a C-L header ?), and semantic (ie:  HEAD request
doesn't have body, even if the response has C-L etc.)
parent 9d70a57e
......@@ -1228,7 +1228,6 @@ void *WS_Printf(struct ws *ws, const char *fmt, ...) __printflike(2, 3);
/* cache_rfc2616.c */
void RFC2616_Ttl(struct busyobj *, double now);
enum body_status RFC2616_Body(struct busyobj *, struct dstat *);
unsigned RFC2616_Req_Gzip(const struct http *);
int RFC2616_Do_Cond(const struct req *sp);
void RFC2616_Weaken_Etag(struct http *hp);
......
......@@ -314,9 +314,52 @@ vbf_stp_startfetch(struct worker *wrk, struct busyobj *bo)
/*
* Figure out how the fetch is supposed to happen, before the
* headers are adultered by VCL
* NB: Also sets other wrk variables
*/
bo->htc->body_status = RFC2616_Body(bo, &wrk->stats);
if (!strcasecmp(http_GetMethod(bo->bereq), "head")) {
/*
* A HEAD request can never have a body in the reply,
* no matter what the headers might say.
* [RFC2516 4.3 p33]
*/
wrk->stats.fetch_head++;
bo->htc->body_status = BS_NONE;
} else if (http_GetStatus(bo->beresp) <= 199) {
/*
* 1xx responses never have a body.
* [RFC2616 4.3 p33]
* ... but we should never see them.
*/
wrk->stats.fetch_1xx++;
bo->htc->body_status = BS_ERROR;
} else if (http_IsStatus(bo->beresp, 204)) {
/*
* 204 is "No Content", obviously don't expect a body.
* [RFC2616 10.2.5 p60]
*/
wrk->stats.fetch_204++;
bo->htc->body_status = BS_NONE;
} else if (http_IsStatus(bo->beresp, 304)) {
/*
* 304 is "Not Modified" it has no body.
* [RFC2616 10.3.5 p63]
*/
wrk->stats.fetch_304++;
bo->htc->body_status = BS_NONE;
} else if (bo->htc->body_status == BS_CHUNKED) {
wrk->stats.fetch_chunked++;
} else if (bo->htc->body_status == BS_LENGTH) {
assert(bo->htc->content_length > 0);
bo->content_length = bo->htc->content_length;
wrk->stats.fetch_length++;
} else if (bo->htc->body_status == BS_EOF) {
wrk->stats.fetch_eof++;
} else if (bo->htc->body_status == BS_ERROR) {
wrk->stats.fetch_bad++;
} else if (bo->htc->body_status == BS_NONE) {
wrk->stats.fetch_none++;
} else {
WRONG("wrong bodystatus");
}
if (bo->htc->body_status == BS_ERROR) {
AN (bo->vbc);
......
......@@ -180,116 +180,6 @@ RFC2616_Ttl(struct busyobj *bo, double now)
expp->t_origin, h_date, h_expires, max_age);
}
/*--------------------------------------------------------------------
* Body existence, fetch method and close policy.
*/
enum body_status
RFC2616_Body(struct busyobj *bo, struct dstat *stats)
{
struct http *hp;
char *b;
ssize_t cl;
hp = bo->beresp;
if (!strcasecmp(http_GetMethod(bo->bereq), "head")) {
/*
* A HEAD request can never have a body in the reply,
* no matter what the headers might say.
* [RFC2516 4.3 p33]
*/
stats->fetch_head++;
return (BS_NONE);
}
if (http_GetStatus(hp) <= 199) {
/*
* 1xx responses never have a body.
* [RFC2616 4.3 p33]
* ... but we should never see them.
*/
stats->fetch_1xx++;
return (BS_ERROR);
}
if (http_IsStatus(hp, 204)) {
/*
* 204 is "No Content", obviously don't expect a body.
* [RFC2616 10.2.5 p60]
*/
stats->fetch_204++;
return (BS_NONE);
}
if (http_IsStatus(hp, 304)) {
/*
* 304 is "Not Modified" it has no body.
* [RFC2616 10.3.5 p63]
*/
stats->fetch_304++;
return (BS_NONE);
}
if (http_HdrIs(hp, H_Transfer_Encoding, "chunked")) {
stats->fetch_chunked++;
return (BS_CHUNKED);
}
if (http_GetHdr(hp, H_Transfer_Encoding, &b)) {
VSLb(bo->vsl, SLT_Error, "Illegal Transfer-Encoding:");
stats->fetch_bad++;
return (BS_ERROR);
}
cl = http_GetContentLength(hp);
if (cl == -2) {
VSLb(bo->vsl, SLT_Error, "Bad Content-Length:");
stats->fetch_bad++;
return (BS_ERROR);
}
if (cl > 0) {
stats->fetch_length++;
bo->content_length = cl;
return (BS_LENGTH);
}
if (cl == 0) {
stats->fetch_length++;
return (BS_NONE);
}
if (http_HdrIs(hp, H_Connection, "keep-alive")) {
/*
* Keep alive with neither TE=Chunked or C-Len is impossible.
* We assume a zero length body.
*/
stats->fetch_zero++;
return (BS_NONE);
}
if (http_HdrIs(hp, H_Connection, "close")) {
/*
* In this case, it is safe to just read what comes.
*/
stats->fetch_close++;
return (BS_EOF);
}
if (hp->protover < 11) {
/*
* With no Connection header, assume EOF.
*/
stats->fetch_oldhttp++;
return (BS_EOF);
}
/*
* Fall back to EOF transfer.
*/
stats->fetch_eof++;
return (BS_EOF);
}
/*--------------------------------------------------------------------
* Find out if the request can receive a gzip'ed response
*/
......
......@@ -197,31 +197,23 @@ VSC_F(fetch_head, uint64_t, 1, 'c', info,
)
VSC_F(fetch_length, uint64_t, 1, 'c', info,
"Fetch with Length",
"beresp with Content-Length."
"beresp.body with Content-Length."
)
VSC_F(fetch_chunked, uint64_t, 1, 'c', info,
"Fetch chunked",
"beresp with Chunked."
"beresp.body with Chunked."
)
VSC_F(fetch_eof, uint64_t, 1, 'c', info,
"Fetch EOF",
"beresp with EOF from lack of other info."
"beresp.body with EOF."
)
VSC_F(fetch_bad, uint64_t, 1, 'c', info,
"Fetch bad T-E",
"beresp failed due to unknown Transfer-Encoding."
"beresp.body length/fetch could not be determined."
)
VSC_F(fetch_close, uint64_t, 1, 'c', info,
"Fetch wanted close",
"beresp with EOF due to Connection: Close."
)
VSC_F(fetch_oldhttp, uint64_t, 1, 'c', info,
"Fetch pre HTTP/1.1 closed",
"beresp with EOF due to HTTP < 1.1"
)
VSC_F(fetch_zero, uint64_t, 1, 'c', info,
"Fetch zero len body",
"beresp with EOF due to keep-live but neither Chunked or Len."
VSC_F(fetch_none, uint64_t, 1, 'c', info,
"Fetch no body",
"beresp.body empty"
)
VSC_F(fetch_1xx, uint64_t, 1, 'c', info,
"Fetch no body (1xx)",
......
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