Commit ef9c880d authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Further unify delivery path so that gunzip, esi and direct object

don't replicate common code.



git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@5689 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 253cfa74
......@@ -750,7 +750,6 @@ void WSL_Flush(struct worker *w, int overflow);
/* cache_response.c */
void RES_BuildHttp(struct sess *sp);
void RES_WriteObj(struct sess *sp);
void RES_WriteGunzipObj(struct sess *sp);
/* cache_vary.c */
struct vsb *VRY_Create(const struct sess *sp, const struct http *hp);
......
......@@ -181,20 +181,23 @@ cnt_deliver(struct sess *sp)
if (params->http_gzip_support &&
http_HdrIs(sp->obj->http, H_Content_Encoding, "gzip") &&
!RFC2616_Req_Gzip(sp) &&
sp->wantbody) {
!RFC2616_Req_Gzip(sp)) {
/*
* We don't know what it uncompresses to
* XXX: we could cache that
*/
sp->wrk->res_mode &= ~RES_LEN;
sp->wrk->res_mode |= RES_EOF; /* XXX */
sp->wrk->res_mode |= RES_GUNZIP;
sp->doclose = "gunzip EOF";
}
if (!(sp->wrk->res_mode & (RES_LEN|RES_CHUNKED|RES_EOF))) {
if(sp->http->protover >= 1.1) {
if (sp->obj->len == 0)
/*
* If the object is empty, neither ESI nor GUNZIP
* can make it any different size
*/
sp->wrk->res_mode |= RES_LEN;
else if (sp->http->protover >= 1.1) {
sp->wrk->res_mode |= RES_CHUNKED;
} else {
sp->wrk->res_mode |= RES_EOF;
......
......@@ -858,10 +858,9 @@ ESI_Deliver(struct sess *sp)
char *ws_wm;
struct http http_save;
struct esidata *ed;
unsigned sxid;
unsigned sxid, res_mode;
w = sp->wrk;
WRW_Reserve(w, &sp->fd);
http_save.magic = 0;
ed = sp->obj->esidata;
CHECK_OBJ_NOTNULL(ed, ESIDATA_MAGIC);
......@@ -878,14 +877,16 @@ ESI_Deliver(struct sess *sp)
sp->esis >= params->max_esi_includes)
continue;
if (WRW_FlushRelease(w)) {
if (WRW_Flush(w)) {
vca_close_session(sp, "remote closed");
return;
}
AZ(WRW_FlushRelease(w));
sp->esis++;
obj = sp->obj;
sp->obj = NULL;
res_mode = sp->wrk->res_mode;
/* Save the master objects HTTP state, we may need it later */
if (http_save.magic == 0)
......@@ -935,6 +936,7 @@ ESI_Deliver(struct sess *sp)
assert(sp->step == STP_DONE);
sp->esis--;
sp->obj = obj;
sp->wrk->res_mode = res_mode;
/* Reset the workspace */
WS_Reset(sp->ws, ws_wm);
......@@ -943,13 +945,6 @@ ESI_Deliver(struct sess *sp)
if (sp->fd < 0)
break;
}
/* Restore master objects HTTP state */
if (http_save.magic)
*sp->http = http_save;
if (sp->esis == 0 && sp->http->protover >= 1.1)
(void)WRW_Write(sp->wrk, "0\r\n\r\n", -1);
if (WRW_FlushRelease(sp->wrk))
vca_close_session(sp, "remote closed");
}
/*--------------------------------------------------------------------*/
......
......@@ -233,79 +233,67 @@ RES_BuildHttp(struct sess *sp)
sp->doclose ? "close" : "keep-alive");
}
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------
* We have a gzip'ed object and need to ungzip it for a client which
* does not understand gzip.
*/
void
RES_WriteObj(struct sess *sp)
static void
res_WriteGunzipObj(struct sess *sp, char lenbuf[20])
{
struct storage *st;
unsigned u = 0;
char lenbuf[20];
char *r;
unsigned low, high, ptr, off, len;
struct vgz *vg;
const void *dp;
size_t dl;
int i;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
WRW_Reserve(sp->wrk, &sp->fd);
/*
* If nothing special planned, we can attempt Range support
*/
low = 0;
high = sp->obj->len - 1;
if (!(sp->wrk->res_mode & (RES_ESI|RES_ESI_CHILD|RES_GUNZIP)) &&
params->http_range_support && sp->obj->response == 200 &&
sp->wantbody && http_GetHdr(sp->http, H_Range, &r))
res_dorange(sp, r, &low, &high);
if (sp->wrk->res_mode & RES_GUNZIP) {
assert(sp->wrk->res_mode & RES_EOF);
assert(!(sp->wrk->res_mode & (RES_ESI|RES_ESI_CHILD)));
AN(sp->doclose);
http_Unset(sp->wrk->resp, H_Content_Encoding);
}
vg = VGZ_NewUnzip(sp, sp->ws, sp->wrk->ws);
AN(vg);
/*
* no headers for interior ESI includes
*/
if (!(sp->wrk->res_mode & RES_ESI_CHILD))
sp->acct_tmp.hdrbytes +=
http_Write(sp->wrk, sp->wrk->resp, 1);
VTAILQ_FOREACH(st, &sp->obj->store, list) {
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
u += st->len;
/*
* ESI objects get special delivery
*/
if (sp->wrk->res_mode & RES_ESI) {
if (WRW_FlushRelease(sp->wrk)) {
vca_close_session(sp, "remote closed");
} else if (sp->wantbody)
ESI_Deliver(sp);
return;
}
sp->acct_tmp.bodybytes += st->len;
VSC_main->n_objwrite++;
if (!sp->wantbody) {
/* This was a HEAD request */
assert(sp->esis == 0);
if (WRW_FlushRelease(sp->wrk))
vca_close_session(sp, "remote closed");
return;
VGZ_Feed(vg, st->ptr, st->len);
do {
i = VGZ_Produce(vg, &dp, &dl);
if (dl != 0) {
if (sp->wrk->res_mode & RES_CHUNKED) {
bprintf(lenbuf, "%x\r\n", (unsigned)dl);
(void)WRW_Write(sp->wrk, lenbuf, -1);
}
(void)WRW_Write(sp->wrk, dp, dl);
if (sp->wrk->res_mode & RES_CHUNKED)
(void)WRW_Write(sp->wrk, "\r\n", -1);
if (WRW_Flush(sp->wrk))
break;
}
} while (i == 0);
}
VGZ_Destroy(&vg);
assert(u == sp->obj->len);
}
if (sp->obj->len == 0) {
if (WRW_FlushRelease(sp->wrk))
vca_close_session(sp, "remote closed");
return;
}
/*--------------------------------------------------------------------*/
if (sp->wrk->res_mode & RES_GUNZIP) {
RES_WriteGunzipObj(sp);
return;
}
static void
res_WriteDirObj(struct sess *sp, char lenbuf[20], size_t low, size_t high)
{
unsigned u = 0;
size_t ptr, off, len;
struct storage *st;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
if (sp->wrk->res_mode & RES_CHUNKED) {
assert(sp->wantbody);
sprintf(lenbuf, "%x\r\n", sp->obj->len);
bprintf(lenbuf, "%x\r\n", sp->obj->len);
(void)WRW_Write(sp->wrk, lenbuf, -1);
}
......@@ -352,55 +340,61 @@ RES_WriteObj(struct sess *sp)
(void)WRW_Write(sp->wrk, st->ptr + off, len);
}
assert(u == sp->obj->len);
if ((sp->wrk->res_mode & RES_CHUNKED))
/* post-chunk new line */
if (sp->wrk->res_mode & RES_CHUNKED)
(void)WRW_Write(sp->wrk, "\r\n", -1);
if (WRW_FlushRelease(sp->wrk))
vca_close_session(sp, "remote closed");
}
/*--------------------------------------------------------------------
* We have a gzip'ed object and need to ungzip it for a client which
* does not understand gzip.
*/
/*--------------------------------------------------------------------*/
void
RES_WriteGunzipObj(struct sess *sp)
RES_WriteObj(struct sess *sp)
{
struct storage *st;
unsigned u = 0;
struct vgz *vg;
const void *dp;
size_t dl;
int i;
char *r;
unsigned low, high;
char lenbuf[20];
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
AN(sp->wantbody);
vg = VGZ_NewUnzip(sp, sp->ws, sp->wrk->ws);
AN(vg);
WRW_Reserve(sp->wrk, &sp->fd);
VTAILQ_FOREACH(st, &sp->obj->store, list) {
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
u += st->len;
/*
* If nothing special planned, we can attempt Range support
*/
low = 0;
high = sp->obj->len - 1;
if (!(sp->wrk->res_mode & (RES_ESI|RES_ESI_CHILD|RES_GUNZIP)) &&
params->http_range_support && sp->obj->response == 200 &&
sp->wantbody && http_GetHdr(sp->http, H_Range, &r))
res_dorange(sp, r, &low, &high);
sp->acct_tmp.bodybytes += st->len;
VSC_main->n_objwrite++;
/*
* Always remove C-E if client don't grok it
*/
if (sp->wrk->res_mode & RES_GUNZIP)
http_Unset(sp->wrk->resp, H_Content_Encoding);
VGZ_Feed(vg, st->ptr, st->len);
do {
i = VGZ_Produce(vg, &dp, &dl);
if (dl != 0) {
(void)WRW_Write(sp->wrk, dp, dl);
if (WRW_Flush(sp->wrk))
break;
}
} while (i == 0);
/*
* Send HTTP protocol header, unless interior ESI object
*/
if (!(sp->wrk->res_mode & RES_ESI_CHILD))
sp->acct_tmp.hdrbytes +=
http_Write(sp->wrk, sp->wrk->resp, 1);
if (!sp->wantbody) {
/* This was a HEAD request */
} else if (sp->obj->len == 0) {
/* Nothing to do here */
} else if (sp->wrk->res_mode & RES_ESI) {
ESI_Deliver(sp);
} else if (sp->wrk->res_mode & RES_GUNZIP) {
res_WriteGunzipObj(sp, lenbuf);
} else {
res_WriteDirObj(sp, lenbuf, low, high);
}
VGZ_Destroy(&vg);
assert(u == sp->obj->len);
if (sp->wrk->res_mode & RES_CHUNKED &&
!(sp->wrk->res_mode & RES_ESI_CHILD))
(void)WRW_Write(sp->wrk, "0\r\n\r\n", -1);
if (WRW_FlushRelease(sp->wrk))
vca_close_session(sp, "remote closed");
......
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