]> err.no Git - varnish/commitdiff
TIMBER!
authorphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Fri, 27 Feb 2009 15:20:57 +0000 (15:20 +0000)
committerphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Fri, 27 Feb 2009 15:20:57 +0000 (15:20 +0000)
Move the vcl_fetch{} execution up between fetching the headers and the
body of the backend response.

This makes obj.* unavailable in vcl_fetch{} and replaces it with a
new beresp.* family of variables.

This paves the way for a lot of good stuff, such as streaming pass,
on-the-fly delivery of misses, storage selection based on headers
etc.

git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@3838 d4fa192b-c00b-0410-8231-f00ffab90ce4

27 files changed:
varnish-cache/bin/varnishd/cache.h
varnish-cache/bin/varnishd/cache_backend.c
varnish-cache/bin/varnishd/cache_center.c
varnish-cache/bin/varnishd/cache_fetch.c
varnish-cache/bin/varnishd/cache_http.c
varnish-cache/bin/varnishd/cache_pipe.c
varnish-cache/bin/varnishd/cache_vrt.c
varnish-cache/bin/varnishd/cache_vrt_esi.c
varnish-cache/bin/varnishd/default.vcl
varnish-cache/bin/varnishd/rfc2616.c
varnish-cache/bin/varnishtest/tests/b00015.vtc
varnish-cache/bin/varnishtest/tests/b00018.vtc
varnish-cache/bin/varnishtest/tests/b00028.vtc
varnish-cache/bin/varnishtest/tests/c00001.vtc
varnish-cache/bin/varnishtest/tests/c00009.vtc
varnish-cache/bin/varnishtest/tests/r00251.vtc
varnish-cache/bin/varnishtest/tests/r00412.vtc
varnish-cache/bin/varnishtest/tests/v00000.vtc
varnish-cache/bin/varnishtest/tests/v00001.vtc
varnish-cache/bin/varnishtest/tests/v00010.vtc
varnish-cache/bin/varnishtest/tests/v00016.vtc
varnish-cache/bin/varnishtest/tests/v00018.vtc
varnish-cache/bin/varnishtest/tests/v00020.vtc
varnish-cache/include/vrt_obj.h
varnish-cache/lib/libvcl/vcc_fixed_token.c
varnish-cache/lib/libvcl/vcc_gen_obj.tcl
varnish-cache/lib/libvcl/vcc_obj.c

index 3aeeaa24c56424835bfa5af84f22f7ca36de0120..deb98fafbf3f0b8e19ead3803ed9aebc588b9543 100644 (file)
@@ -242,8 +242,15 @@ struct bereq {
 #define BEREQ_MAGIC            0x3b6d250c
        VTAILQ_ENTRY(bereq)     list;
        struct ws               ws[1];
-       struct http             http[2];
+       struct http             bereq[1];
+       struct http             beresp[2];
        struct http_conn        htc[1];
+       unsigned                cacheable;
+       double                  age;
+       double                  entered;
+       double                  ttl;
+       double                  grace;
+       unsigned                do_esi;
 };
 
 /* Storage -----------------------------------------------------------*/
@@ -639,6 +646,7 @@ void VCL_Poll(void);
 
 void ESI_Deliver(struct sess *);
 void ESI_Destroy(struct object *);
+void ESI_Parse(struct sess *);
 
 /* cache_ws.c */
 
@@ -654,7 +662,7 @@ char *WS_Snapshot(struct ws *ws);
 unsigned WS_Free(const struct ws *ws);
 
 /* rfc2616.c */
-int RFC2616_cache_policy(const struct sess *sp, const struct http *hp);
+double RFC2616_Ttl(const struct sess *sp);
 
 /* storage_synth.c */
 struct vsb *SMS_Makesynth(struct object *obj);
index 3637feddd91ff14f63afbf26196a21b8919e2fe1..44e16012451c589b12083c7aea9a93052f164fbd 100644 (file)
@@ -65,10 +65,10 @@ VBE_AddHostHeader(const struct sess *sp)
 
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
        CHECK_OBJ_NOTNULL(sp->bereq, BEREQ_MAGIC);
-       CHECK_OBJ_NOTNULL(sp->bereq->http, HTTP_MAGIC);
+       CHECK_OBJ_NOTNULL(sp->bereq->bereq, HTTP_MAGIC);
        CHECK_OBJ_NOTNULL(sp->vbe, VBE_CONN_MAGIC);
        CHECK_OBJ_NOTNULL(sp->vbe->backend, BACKEND_MAGIC);
-       http_PrintfHeader(sp->wrk, sp->fd, sp->bereq->http,
+       http_PrintfHeader(sp->wrk, sp->fd, sp->bereq->bereq,
            "Host: %s", sp->vbe->backend->hosthdr);
 }
 
@@ -163,8 +163,8 @@ VBE_new_bereq(void)
                WS_Init(bereq->ws, "bereq", bereq + 1, len);
                VSL_stats->n_bereq++;
        }
-       http_Setup(&bereq->http[0], bereq->ws);
-       http_Setup(&bereq->http[1], bereq->ws);
+       http_Setup(bereq->bereq, bereq->ws);
+       http_Setup(bereq->beresp, bereq->ws);
        return (bereq);
 }
 
index e04847500a6667fc73bc5f9d613c46e114a07aa3..2e23fc8a8d1e284b7db4a4ac72041daa41a0deae 100644 (file)
@@ -378,6 +378,8 @@ static int
 cnt_fetch(struct sess *sp)
 {
        int i;
+       struct http *hp, *hp2;
+       char *b;
 
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
        CHECK_OBJ_NOTNULL(sp->vcl, VCL_CONF_MAGIC);
@@ -388,10 +390,79 @@ cnt_fetch(struct sess *sp)
 
        sp->obj->xid = sp->xid;
        WS_Assert(sp->obj->ws_o);
+
        i = FetchHdr(sp);
+
+       /*
+        * Save a copy before it might get mangled in VCL.  When it comes to
+        * dealing with the body, we want to see the unadultered headers.
+        */
+       sp->bereq->beresp[1] = sp->bereq->beresp[0];
+
+       if (i) {
+               sp->err_code = 503;
+               sp->step = STP_ERROR;
+               VBE_free_bereq(&sp->bereq);
+               HSH_Drop(sp);
+               AZ(sp->obj);
+               return (0);
+       }
+
+       sp->err_code = http_GetStatus(sp->bereq->beresp);
+
+       /*
+        * Initial cacheability determination per [RFC2616, 13.4]
+        * We do not support ranges yet, so 206 is out.
+        */
+       switch (sp->err_code) {
+       case 200: /* OK */
+       case 203: /* Non-Authoritative Information */
+       case 300: /* Multiple Choices */
+       case 301: /* Moved Permanently */
+       case 302: /* Moved Temporarily */
+       case 410: /* Gone */
+       case 404: /* Not Found */
+               sp->bereq->cacheable = 1;
+               break;
+       default:
+               sp->bereq->cacheable = 0;
+               break;
+       }
+
+       sp->bereq->entered = TIM_real();
+       sp->bereq->age = 0;
+       sp->bereq->ttl = RFC2616_Ttl(sp);
+
+       if (sp->bereq->ttl == 0.)
+               sp->bereq->cacheable = 0;
+
+       sp->bereq->do_esi = 0;
+       sp->bereq->grace = NAN;
+
+       VCL_fetch_method(sp);
+
+       sp->obj->response = sp->err_code;
+       sp->obj->cacheable = sp->bereq->cacheable;
+       sp->obj->ttl = sp->bereq->ttl;
+       sp->obj->grace = sp->bereq->grace;
+       if (sp->obj->ttl == 0.)
+               sp->obj->cacheable = 0;
+       sp->obj->age = sp->bereq->age;
+       sp->obj->entered = sp->bereq->entered;
+
+       /* Filter into object */
+       hp = sp->bereq->beresp;
+       hp2 = sp->obj->http;
+
+       hp2->logtag = HTTP_Obj;
+       http_CopyResp(hp2, hp);
+       http_FilterFields(sp->wrk, sp->fd, hp2, hp, HTTPH_A_INS);
+       http_CopyHome(sp->wrk, sp->fd, hp2);
+
+       if (http_GetHdr(hp, H_Last_Modified, &b))
+               sp->obj->last_modified = TIM_parse(b);
        
-       if (i == 0)
-               i = FetchBody(sp);
+       i = FetchBody(sp);
        AZ(sp->wrk->wfd);
        AZ(sp->vbe);
        AN(sp->director);
@@ -405,10 +476,8 @@ cnt_fetch(struct sess *sp)
                return (0);
        }
 
-       RFC2616_cache_policy(sp, sp->obj->http);        /* XXX -> VCL */
-
-       sp->err_code = http_GetStatus(sp->obj->http);
-       VCL_fetch_method(sp);
+       if (sp->bereq->do_esi)
+               ESI_Parse(sp);
 
        VBE_free_bereq(&sp->bereq);
 
index ef50042ce21a4d283454466e8dbfca607d1206f6..2990065133c52e26c6b4604940de98170a7b6bcc 100644 (file)
@@ -330,7 +330,7 @@ FetchHdr(struct sess *sp)
 
        w = sp->wrk;
        bereq = sp->bereq;
-       hp = &bereq->http[0];
+       hp = bereq->bereq;
 
        VBE_GetFd(sp);
        if (sp->vbe == NULL)
@@ -381,7 +381,7 @@ FetchHdr(struct sess *sp)
                return (__LINE__);
        }
 
-       hp = &bereq->http[1];
+       hp = bereq->beresp;
 
        if (http_DissectResponse(sp->wrk, bereq->htc, hp)) {
                VBE_ClosedFd(sp);
@@ -399,15 +399,18 @@ FetchBody(struct sess *sp)
        struct vbe_conn *vc;
        char *b;
        int cls;
-       struct http *hp, *hp2;
+       struct http *hp;
        struct storage *st;
        int mklen, is_head;
 
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
        CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC);
        CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);
+       CHECK_OBJ_NOTNULL(sp->obj->http, HTTP_MAGIC);
        CHECK_OBJ_NOTNULL(sp->bereq, BEREQ_MAGIC);
-       hp = &sp->bereq->http[1];
+
+       /* We use the unmodified headers */
+       hp = &sp->bereq->beresp[1];
        AN(sp->director);
        if (sp->obj->objcore != NULL)           /* pass has no objcore */
                AN(ObjIsBusy(sp->obj));
@@ -415,19 +418,7 @@ FetchBody(struct sess *sp)
 
        vc = sp->vbe;
 
-       sp->obj->entered = TIM_real();
-       is_head = (strcasecmp(http_GetReq(&sp->bereq->http[0]), "head") == 0);
-
-       if (http_GetHdr(hp, H_Last_Modified, &b))
-               sp->obj->last_modified = TIM_parse(b);
-
-       /* Filter into object */
-       hp2 = sp->obj->http;
-
-       hp2->logtag = HTTP_Obj;
-       http_CopyResp(hp2, hp);
-       http_FilterFields(sp->wrk, sp->fd, hp2, hp, HTTPH_A_INS);
-       http_CopyHome(sp->wrk, sp->fd, hp2);
+       is_head = (strcasecmp(http_GetReq(sp->bereq->bereq), "head") == 0);
 
        /* Determine if we have a body or not */
        cls = 0;
@@ -495,7 +486,7 @@ FetchBody(struct sess *sp)
        }
 
        if (mklen > 0)
-               http_PrintfHeader(sp->wrk, sp->fd, hp2,
+               http_PrintfHeader(sp->wrk, sp->fd, sp->obj->http,
                    "Content-Length: %u", sp->obj->len);
 
        if (http_HdrIs(hp, H_Connection, "close")) 
index f83da38401f462911d8caf72d880916cdc7797e6..0edade0db86d522cc56f386a57bd7506f81dc3e7 100644 (file)
@@ -637,7 +637,7 @@ http_FilterHeader(struct sess *sp, unsigned how)
        AZ(sp->bereq);
        bereq = VBE_new_bereq();
        AN(bereq);
-       hp = bereq->http;
+       hp = bereq->bereq;
        hp->logtag = HTTP_Tx;
 
        http_copyreq(hp, sp->http, how);
index eb725a3c9f7d7be721b6556d208a3f5038aae337..a74ca958d5f9b9b6675f27dce0ea92316df620ca 100644 (file)
@@ -84,7 +84,7 @@ PipeSession(struct sess *sp)
        TCP_blocking(vc->fd);
 
        WRW_Reserve(w, &vc->fd);
-       sp->acct_req.hdrbytes += http_Write(w, bereq->http, 0);
+       sp->acct_req.hdrbytes += http_Write(w, bereq->bereq, 0);
 
        if (sp->htc->pipeline.b != NULL)
                sp->acct_req.bodybytes +=
index d4a5a8e2891632690300f543864172ab02ae3d05..20be6e35c8d053e26a2a96d81ba70b560fd13b98 100644 (file)
@@ -100,10 +100,10 @@ vrt_selecthttp(const struct sess *sp, enum gethdr_e where)
                hp = sp->http;
                break;
        case HDR_BEREQ:
-               hp = &sp->bereq->http[0];
+               hp = sp->bereq->bereq;
                break;
        case HDR_BERESP:
-               hp = &sp->bereq->http[1];
+               hp = sp->bereq->beresp;
                break;
        case HDR_RESP:
                hp = sp->http;
@@ -243,13 +243,15 @@ VRT_r_##obj##_##hdr(const struct sess *sp)                        \
 VRT_DO_HDR(req,   request,     sp->http,               HTTP_HDR_REQ)
 VRT_DO_HDR(req,   url,         sp->http,               HTTP_HDR_URL)
 VRT_DO_HDR(req,   proto,       sp->http,               HTTP_HDR_PROTO)
-VRT_DO_HDR(bereq, request,     sp->bereq->http,        HTTP_HDR_REQ)
-VRT_DO_HDR(bereq, url,         sp->bereq->http,        HTTP_HDR_URL)
-VRT_DO_HDR(bereq, proto,       sp->bereq->http,        HTTP_HDR_PROTO)
+VRT_DO_HDR(bereq, request,     sp->bereq->bereq,       HTTP_HDR_REQ)
+VRT_DO_HDR(bereq, url,         sp->bereq->bereq,       HTTP_HDR_URL)
+VRT_DO_HDR(bereq, proto,       sp->bereq->bereq,       HTTP_HDR_PROTO)
 VRT_DO_HDR(obj,   proto,       sp->obj->http,          HTTP_HDR_PROTO)
 VRT_DO_HDR(obj,   response,    sp->obj->http,          HTTP_HDR_RESPONSE)
 VRT_DO_HDR(resp,  proto,       sp->http,               HTTP_HDR_PROTO)
 VRT_DO_HDR(resp,  response,    sp->http,               HTTP_HDR_RESPONSE)
+VRT_DO_HDR(beresp,  proto,     sp->bereq->beresp,      HTTP_HDR_PROTO)
+VRT_DO_HDR(beresp,  response,  sp->bereq->beresp,      HTTP_HDR_RESPONSE)
 
 /*--------------------------------------------------------------------*/
 
@@ -277,6 +279,7 @@ VRT_r_obj_status(const struct sess *sp)
        /* XXX: use http_GetStatus() */
        if (sp->obj->http->status)
                return (sp->obj->http->status);
+       AN(sp->obj->http->hd[HTTP_HDR_STATUS].b);
        return (atoi(sp->obj->http->hd[HTTP_HDR_STATUS].b));
 }
 
@@ -302,6 +305,93 @@ VRT_r_resp_status(const struct sess *sp)
        return (atoi(sp->http->hd[HTTP_HDR_STATUS].b));
 }
 
+/*--------------------------------------------------------------------*/
+
+#define VBEREQ(dir, type,onm,field)                                    \
+void                                                                   \
+VRT_l_##dir##_##onm(const struct sess *sp, type a)                     \
+{                                                                      \
+       CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);                              \
+       CHECK_OBJ_NOTNULL(sp->bereq, BEREQ_MAGIC);      /* XXX */       \
+       sp->bereq->field = a;                                           \
+}                                                                      \
+                                                                       \
+type                                                                   \
+VRT_r_##dir##_##onm(const struct sess *sp)                             \
+{                                                                      \
+       CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);                              \
+       CHECK_OBJ_NOTNULL(sp->bereq, BEREQ_MAGIC);      /* XXX */       \
+       return (sp->bereq->field);                                      \
+}
+
+VBEREQ(beresp, unsigned, cacheable, cacheable)
+VBEREQ(beresp, double, grace, grace)
+
+/*--------------------------------------------------------------------
+ * XXX: Working relative to t_req is maybe not the right thing, we could
+ * XXX: have spent a long time talking to the backend since then.
+ * XXX: It might make sense to cache a timestamp as "current time"
+ * XXX: before vcl_recv (== t_req) and vcl_fetch.
+ * XXX: On the other hand, that might lead to inconsistent behaviour
+ * XXX: where an object expires while we are running VCL code, and
+ * XXX: and that may not be a good idea either.
+ * XXX: See also related t_req use in cache_hash.c
+ */
+
+void
+VRT_l_beresp_ttl(const struct sess *sp, double a)
+{
+
+       CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+       CHECK_OBJ_NOTNULL(sp->bereq, BEREQ_MAGIC);      /* XXX */
+       WSP(sp, SLT_TTL, "%u VCL %.0f %.0f", sp->xid, a, sp->t_req);
+       /*
+        * If people set obj.ttl = 0s, they don't expect it to be cacheable
+        * any longer, but it will still be for up to 1s - epsilon because
+        * of the rounding to seconds.
+        * We special case and make sure that rounding does not surprise.
+        */
+       if (a <= 0)
+               sp->bereq->ttl = sp->t_req - 1;
+       else
+               sp->bereq->ttl = sp->t_req + a;
+}
+
+double
+VRT_r_beresp_ttl(const struct sess *sp)
+{
+       CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+       CHECK_OBJ_NOTNULL(sp->bereq, BEREQ_MAGIC);      /* XXX */
+       return (sp->bereq->ttl - sp->t_req);
+}
+
+void
+VRT_l_beresp_status(const struct sess *sp, int num)
+{
+       char *p;
+
+       assert(num >= 100 && num <= 999);
+       p = WS_Alloc(sp->obj->http->ws, 4);
+       if (p == NULL)
+               WSP(sp, SLT_LostHeader, "%s", "obj.status");
+       else
+               sprintf(p, "%d", num);
+       http_SetH(sp->bereq->beresp, HTTP_HDR_STATUS, p);
+}
+
+int
+VRT_r_beresp_status(const struct sess *sp)
+{
+       CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+       CHECK_OBJ_NOTNULL(sp->bereq, BEREQ_MAGIC);
+       /* XXX: use http_GetStatus() */
+       if (sp->bereq->beresp->status)
+               return (sp->bereq->beresp->status);
+       AN(sp->bereq->beresp->hd[HTTP_HDR_STATUS].b);
+       return (atoi(sp->bereq->beresp->hd[HTTP_HDR_STATUS].b));
+}
+
+
 void
 VRT_l_bereq_connect_timeout(struct sess *sp, double num)
 {
index b6af0a359c59785893d19acec831f23394fbc2a7..7bf3c935ca0078e23c8c50daad518deb216ce3ff 100644 (file)
@@ -398,8 +398,8 @@ esi_handle_include(struct esi_work *ew)
                         */
                        CHECK_OBJ_NOTNULL(ew->sp, SESS_MAGIC);
                        CHECK_OBJ_NOTNULL(ew->sp->bereq, BEREQ_MAGIC);
-                       CHECK_OBJ_NOTNULL(ew->sp->bereq->http, HTTP_MAGIC);
-                       tag = ew->sp->bereq->http->hd[HTTP_HDR_URL];
+                       CHECK_OBJ_NOTNULL(ew->sp->bereq->bereq, HTTP_MAGIC);
+                       tag = ew->sp->bereq->bereq->hd[HTTP_HDR_URL];
 
                        /* Use the objects WS to store the result */
                        CHECK_OBJ_NOTNULL(ew->sp->obj, OBJECT_MAGIC);
@@ -639,12 +639,8 @@ parse_esi_tag(struct esi_work *ew, int closing)
 void
 VRT_ESI(struct sess *sp)
 {
-       struct esi_work *ew, eww[1];
+       CHECK_OBJ_NOTNULL(sp->bereq, BEREQ_MAGIC);
 
-       CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
-       CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);
-       if (sp->obj->objcore != NULL)   /* Pass has no objcore */
-               AN(ObjIsBusy(sp->obj));
        if (sp->cur_method != VCL_MET_FETCH) {
                /* XXX: we should catch this at compile time */
                WSP(sp, SLT_VCL_error,
@@ -652,6 +648,19 @@ VRT_ESI(struct sess *sp)
                return;
        }
 
+       sp->bereq->do_esi = 1;
+}
+
+
+void
+ESI_Parse(struct sess *sp)
+{
+       struct esi_work *ew, eww[1];
+
+       CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+       CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);
+       if (sp->obj->objcore != NULL)   /* Pass has no objcore */
+               AN(ObjIsBusy(sp->obj));
        if (VTAILQ_EMPTY(&sp->obj->store))
                return;
 
index dcf144ac8fbeecfc110c290180b9d385346bb8e0..048a5f99c7b66e62de35a9620c9cc7e1b70b43cb 100644 (file)
@@ -91,10 +91,10 @@ sub vcl_miss {
 }
 
 sub vcl_fetch {
-    if (!obj.cacheable) {
+    if (!beresp.cacheable) {
         return (pass);
     }
-    if (obj.http.Set-Cookie) {
+    if (beresp.http.Set-Cookie) {
         return (pass);
     }
     return (deliver);
index 66c63ab1f8a499b28dca5b4032cb84b62c0a0f4b..dc1312f4f2e6208219400c646d6013f3374a7464 100644 (file)
  *
  */
 
-static double
-RFC2616_Ttl(const struct sess *sp, const struct http *hp, struct object *obj)
+double
+RFC2616_Ttl(const struct sess *sp)
 {
        int ttl;
        unsigned max_age, age;
        double h_date, h_expires, ttd;
        char *p;
+       const struct http *hp;
 
-       assert(obj->entered != 0.0 && !isnan(sp->obj->entered));
+       CHECK_OBJ_NOTNULL(sp->bereq, BEREQ_MAGIC);
+       hp = sp->bereq->beresp;
+
+       assert(sp->bereq->entered != 0.0 && !isnan(sp->bereq->entered));
        /* If all else fails, cache using default ttl */
        ttl = params->default_ttl;
 
@@ -99,7 +103,7 @@ RFC2616_Ttl(const struct sess *sp, const struct http *hp, struct object *obj)
                        max_age = strtoul(p, NULL, 0);
                        if (http_GetHdr(hp, H_Age, &p)) {
                                age = strtoul(p, NULL, 0);
-                               obj->age = age;
+                               sp->bereq->age = age;
                        }
 
                        if (age > max_age)
@@ -126,14 +130,14 @@ RFC2616_Ttl(const struct sess *sp, const struct http *hp, struct object *obj)
                }
 
                if (h_date == 0 ||
-                   (h_date < obj->entered + params->clock_skew &&
-                   h_date + params->clock_skew > obj->entered)) {
+                   (h_date < sp->bereq->entered + params->clock_skew &&
+                   h_date + params->clock_skew > sp->bereq->entered)) {
                        /*
                         * If we have no Date: header or if it is
                         * sufficiently close to our clock we will
                         * trust Expires: relative to our own clock.
                         */
-                       if (h_expires < obj->entered)
+                       if (h_expires < sp->bereq->entered)
                                ttl = 0;
                        else
                                ttd = h_expires;
@@ -150,58 +154,13 @@ RFC2616_Ttl(const struct sess *sp, const struct http *hp, struct object *obj)
        } while (0);
 
        if (ttl > 0 && ttd == 0)
-               ttd = obj->entered + ttl;
+               ttd = sp->bereq->entered + ttl;
 
        /* calculated TTL, Our time, Date, Expires, max-age, age */
        WSP(sp, SLT_TTL, "%u RFC %d %d %d %d %u %u", sp->xid,
-           ttd ? (int)(ttd - obj->entered) : 0,
-           (int)obj->entered, (int)h_date,
+           ttd ? (int)(ttd - sp->bereq->entered) : 0,
+           (int)sp->bereq->entered, (int)h_date,
            (int)h_expires, max_age, age);
 
        return (ttd);
 }
-
-/*
- * We could move this policy to vcl_fetch{} now but I have decided to leave
- * it here for the POLA principle.  It is not credible to think that a
- * majority of our uses will change the cacheability decision, so moving
- * it to VCL would just make the average and median vcl_fetch{} implementation
- * harder for people to write.  Instead the minority who want to override
- * the RFC2616 mandated behaviour, can do so in their vcl_fetch{}
- */
-int
-RFC2616_cache_policy(const struct sess *sp, const struct http *hp)
-{
-       int body = 0;
-       double ttl;
-
-       /*
-        * Initial cacheability determination per [RFC2616, 13.4]
-        * We do not support ranges yet, so 206 is out.
-        */
-       sp->obj->response = http_GetStatus(hp);
-       switch (sp->obj->response) {
-       case 200: /* OK */
-       case 203: /* Non-Authoritative Information */
-       case 300: /* Multiple Choices */
-       case 301: /* Moved Permanently */
-       case 302: /* Moved Temporarily */
-       case 410: /* Gone */
-       case 404: /* Not Found */
-               sp->obj->cacheable = 1;
-               body = 1;
-               break;
-       default:
-               sp->obj->cacheable = 0;
-               body = 0;
-               break;
-       }
-
-       ttl = RFC2616_Ttl(sp, hp, sp->obj);
-       sp->obj->ttl = ttl;
-       if (ttl == 0)
-               sp->obj->cacheable = 0;
-
-       return (body);
-}
-
index a131a9605e459b9420a1535e091bb405fe1b8674..6d5c608c6c82510f31a6570498cf4d9779fea2ae 100644 (file)
@@ -57,9 +57,9 @@ server s1 {
 
 varnish v1 -vcl+backend {
        sub vcl_fetch {
-               if (obj.status == 502) {
-                       set obj.cacheable = true;
-                       set obj.ttl = 10m;
+               if (beresp.status == 502) {
+                       set beresp.cacheable = true;
+                       set beresp.ttl = 10m;
                }
        }
 }
index 3ff45f6405f8486c4aa645f2d6fdf19911a15af3..24329ef920dded8044a8ee91bc7164210c1c0283 100644 (file)
@@ -9,7 +9,7 @@ server s1 {
 
 varnish v1 -vcl+backend { 
        sub vcl_fetch {
-           set obj.http.Foo = "bar";
+           set beresp.http.Foo = "bar";
            error 523 "not ok";
        }
 } -start
index 95fd593dd7c1f711d8aab9954f8315238cc470ce..85a8a01c911eb85031bf98a6551d14d8b534cced 100644 (file)
@@ -10,11 +10,15 @@ server s1 {
 varnish v1 -vcl+backend {
 
        sub vcl_fetch {
-               if (obj.http.foo ~ "bar") {
-                       set obj.http.foo1 = "1";
+               if (beresp.http.foo ~ "bar") {
+                       set beresp.http.foo1 = "1";
+               } else {
+                       error 999;
                }
-               if (obj.http.bar !~ "bar") {
-                       set obj.http.bar1 = "1";
+               if (beresp.http.bar !~ "bar") {
+                       set beresp.http.bar1 = "2";
+               } else {
+                       error 999;
                }
        }
 
@@ -24,5 +28,5 @@ client c1 {
        txreq
        rxresp
        expect resp.http.foo1 == "1"
-       expect resp.http.bar1 == "1"
+       expect resp.http.bar1 == "2"
 } -run
index ccbf65389d88ead896ce80aaacba17e4888f694e..7c6f516b27a626df5c77f8eb8e6caa6d0ee1a036 100644 (file)
@@ -12,17 +12,17 @@ server s1 {
 
 varnish v1 -vcl+backend { 
        sub vcl_fetch {
-               set obj.http.Snafu1 = regsub(obj.http.Foobar, "ar", "\0\0");
-               set obj.http.Snafu2 =
-                   regsub(obj.http.Foobar, "(b)(a)(r)(f)", "\4\3\2p");
-               set obj.http.Snafu3 =
-                   regsub(obj.http.Foobar, "(b)(a)(r)(f)", "\4\\\3\2p");
-               set obj.http.Snafu4 =
-                   regsub(obj.http.Foobar, "(b)(a)(r)(f)", "\4\&\3\2p");
-               set obj.http.Snafu5 =
-                   regsub(obj.http.Foobar, "(b)(a)(r)(f)", "\0\4\3\2\\p");
-               set obj.http.Snafu6 =
-                   regsub(obj.http.Foobar, "(b)(a)(r)(f)", "\4\&\3\2p\");
+               set beresp.http.Snafu1 = regsub(beresp.http.Foobar, "ar", "\0\0");
+               set beresp.http.Snafu2 =
+                   regsub(beresp.http.Foobar, "(b)(a)(r)(f)", "\4\3\2p");
+               set beresp.http.Snafu3 =
+                   regsub(beresp.http.Foobar, "(b)(a)(r)(f)", "\4\\\3\2p");
+               set beresp.http.Snafu4 =
+                   regsub(beresp.http.Foobar, "(b)(a)(r)(f)", "\4\&\3\2p");
+               set beresp.http.Snafu5 =
+                   regsub(beresp.http.Foobar, "(b)(a)(r)(f)", "\0\4\3\2\\p");
+               set beresp.http.Snafu6 =
+                   regsub(beresp.http.Foobar, "(b)(a)(r)(f)", "\4\&\3\2p\");
        }
 } -start 
 
index 292412358f8d140bb55d7a577ae0ea15e13c1ce0..999ca0e91343e38de795a1658b1489e573b2c2d3 100644 (file)
@@ -24,7 +24,7 @@ varnish v1 -vcl+backend {
        }
 
        sub vcl_fetch {
-               if (obj.status != 200) {
+               if (beresp.status != 200) {
                        restart;
                }
        }
index 86879b30eae92e8ec217e99126232139984b2913..57c40d43c96398b69f8c724e39405452b4a1cb7f 100644 (file)
@@ -12,9 +12,9 @@ server s1 {
 
 varnish v1 -vcl+backend { 
        sub vcl_fetch {
-               set obj.http.Snafu1 =
+               set beresp.http.Snafu1 =
                    "zoom"
-                   regsub(obj.http.Foomble, "ar", "\0\0")
+                   regsub(beresp.http.Foomble, "ar", "\0\0")
                    "box";
        }
 } -start 
index 87bfdaf835ef4544ee321646b224845628308b41..4153e4e9bc896382bdd203cb61997f7364bea503 100644 (file)
@@ -13,11 +13,11 @@ server s1 {
 
 varnish v1 -vcl+backend {
        sub vcl_fetch {
-               if (obj.status == 303) {
-                       set obj.cacheable = true;
-                       set obj.ttl = 60 s;
-                       set obj.http.X-Magic-Redirect = "1";
-                       set req.url = obj.http.Location;
+               if (beresp.status == 303) {
+                       set beresp.cacheable = true;
+                       set beresp.ttl = 60 s;
+                       set beresp.http.X-Magic-Redirect = "1";
+                       set req.url = beresp.http.Location;
                        restart;
                }
        }
index 43743d4344f98b3c34b0d4478e86fdb60dcc638e..ac565cb3b1b41e48409be3606f3b7c42eb2d721b 100644 (file)
@@ -15,8 +15,8 @@ varnish v1 -vcl+backend {
                set req.grace += 1 s;
        }
        sub vcl_fetch {
-               set obj.ttl += 1 m;
-               set obj.grace += 1 h;
+               set beresp.ttl += 1 m;
+               set beresp.grace += 1 h;
        }
 } -start
 
index c912bc8aa2bf4be6a1f62b17b5d4e27d0333ffb0..404b4acc539966072036df33a66c20501fd0e83c 100644 (file)
@@ -29,11 +29,11 @@ varnish v1 -vcl+backend {
                set bereq.request = "GET";
        }
        sub vcl_fetch {
-               set obj.http.foobar =
-                   obj.proto obj.response obj.status;
-               set obj.proto = "HTTP/1.2";
-               set obj.response = "For circular files";
-               set obj.status = 903;
+               set beresp.http.foobar =
+                   beresp.proto beresp.response beresp.status;
+               set beresp.proto = "HTTP/1.2";
+               set beresp.response = "For circular files";
+               set beresp.status = 903;
        }
        sub vcl_deliver {
                set resp.proto = "HTTP/1.2";
index c534cdf09184ffc724d11ec299b48c2c653953f4..ee9049d23e7cec45703b445d0ba45bb9102ebb5f 100644 (file)
@@ -13,8 +13,8 @@ server s1 {
 varnish v1 -vcl+backend {
 
        sub vcl_fetch {
-               if (obj.http.panic) {
-                       panic "Had Panic header: " obj.http.panic;
+               if (beresp.http.panic) {
+                       panic "Had Panic header: " beresp.http.panic;
                }
        }
 } -start
index a70a563f021c881676bdfebfb3ca52721b554b5a..f4570c07b3485e01b700e940cbf17a372328c5ee 100644 (file)
@@ -63,13 +63,13 @@ varnish v1 -vcl {
 
        /* test time and backend comparison */
        sub vcl_fetch {
-               if (obj.ttl > 1d) {
-                       set obj.ttl = 1d;
+               if (beresp.ttl > 1d) {
+                       set beresp.ttl = 1d;
                }
                if (req.backend == b) {
-                       set obj.ttl = 1d;
+                       set beresp.ttl = 1d;
                } else if (req.backend != b) {
-                       set obj.ttl = 1h;
+                       set beresp.ttl = 1h;
                }
        }
        
index 9f3dcbd0b38cdcd68c2e3ba2c8e604c9431d77c3..bf94c6c8f3eefc758ed60c71b7b571344329f76a 100644 (file)
@@ -15,14 +15,14 @@ varnish v1 -badvcl {
 
 varnish v1 -vcl {
        backend b { .host = "127.0.0.1"; }
-       sub vcl_fetch { error obj.status ; }
+       sub vcl_fetch { error beresp.status ; }
 }
 
 varnish v1 -vcl {
        backend b { .host = "127.0.0.1"; }
        sub vcl_miss { error req.url ; }
        sub vcl_pass { error "the butter please" ; }
-       sub vcl_fetch { error obj.status req.url; }
+       sub vcl_fetch { error beresp.status req.url; }
 }
 
 varnish v1 -badvcl {
@@ -37,12 +37,12 @@ varnish v1 -badvcl {
 
 varnish v1 -vcl {
        backend b { .host = "127.0.0.1"; }
-       sub vcl_fetch { set obj.ttl /= 2; }
+       sub vcl_fetch { set beresp.ttl /= 2; }
 }
 
 varnish v1 -badvcl {
        backend b { .host = "127.0.0.1"; }
-       sub vcl_fetch { set obj.ttl >>= 2; }
+       sub vcl_fetch { set beresp.ttl >>= 2; }
 }
 
 varnish v1 -badvcl {
@@ -78,22 +78,22 @@ varnish v1 -badvcl {
 
 varnish v1 -vcl {
        backend b { .host = "127.0.0.1"; }
-       sub vcl_fetch { set obj.cacheable = true; }
+       sub vcl_fetch { set beresp.cacheable = true; }
 }
 
 varnish v1 -vcl {
        backend b { .host = "127.0.0.1"; }
-       sub vcl_fetch { set obj.cacheable = false; }
+       sub vcl_fetch { set beresp.cacheable = false; }
 }
 
 varnish v1 -badvcl {
        backend b { .host = "127.0.0.1"; }
-       sub vcl_fetch { set obj.cacheable = mu; }
+       sub vcl_fetch { set beresp.cacheable = mu; }
 }
 
 varnish v1 -badvcl {
        backend b { .host = "127.0.0.1"; }
-       sub vcl_fetch { unset obj.cacheable; }
+       sub vcl_fetch { unset beresp.cacheable; }
 }
 
 varnish v1 -badvcl {
index ca3441d9f805207ef8730002353aa21453df8fd0..8e7dafb0ebcd201646ee9defa67d08379e9d80a3 100644 (file)
@@ -16,7 +16,7 @@ varnish v1 -badvcl " sub vcl_recv { { } { "
 varnish v1 -vcl {
        backend b { .host = "127.0.0.1"; }
        sub vcl_fetch {
-               set obj.ttl = 1w;
+               set beresp.ttl = 1w;
        }
 }
 
index 66f03b70f5b9eca61f4ad0364c1824014f835ae2..b781e9e8a7505fbed1a91d9dab1574b160917b2e 100644 (file)
@@ -34,12 +34,18 @@ double VRT_r_bereq_first_byte_timeout(struct sess *);
 void VRT_l_bereq_first_byte_timeout(struct sess *, double);
 double VRT_r_bereq_between_bytes_timeout(struct sess *);
 void VRT_l_bereq_between_bytes_timeout(struct sess *, double);
-const char * VRT_r_beresp_request(const struct sess *);
-void VRT_l_beresp_request(const struct sess *, const char *, ...);
-const char * VRT_r_beresp_url(const struct sess *);
-void VRT_l_beresp_url(const struct sess *, const char *, ...);
 const char * VRT_r_beresp_proto(const struct sess *);
 void VRT_l_beresp_proto(const struct sess *, const char *, ...);
+int VRT_r_beresp_status(const struct sess *);
+void VRT_l_beresp_status(const struct sess *, int);
+const char * VRT_r_beresp_response(const struct sess *);
+void VRT_l_beresp_response(const struct sess *, const char *, ...);
+unsigned VRT_r_beresp_cacheable(const struct sess *);
+void VRT_l_beresp_cacheable(const struct sess *, unsigned);
+double VRT_r_beresp_ttl(const struct sess *);
+void VRT_l_beresp_ttl(const struct sess *, double);
+double VRT_r_beresp_grace(const struct sess *);
+void VRT_l_beresp_grace(const struct sess *, double);
 const char * VRT_r_obj_proto(const struct sess *);
 void VRT_l_obj_proto(const struct sess *, const char *, ...);
 int VRT_r_obj_status(const struct sess *);
index cf88ce3a38f9aa68489a57c8ef7542007f709741..af2e2aad7d399363a33f48d977b99ffb70c25d38 100644 (file)
@@ -233,8 +233,8 @@ vcl_output_lang_h(struct vsb *sb)
        vsb_cat(sb, " * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWI");
        vsb_cat(sb, "SE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFT");
        vsb_cat(sb, "WARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n");
-       vsb_cat(sb, " * SUCH DAMAGE.\n *\n * $Id: vrt.h 3542 2009-01-24 10:");
-       vsb_cat(sb, "36:46Z phk $\n *\n * Runtime support for compiled VCL ");
+       vsb_cat(sb, " * SUCH DAMAGE.\n *\n * $Id: vrt.h 3834 2009-02-27 12:");
+       vsb_cat(sb, "02:50Z phk $\n *\n * Runtime support for compiled VCL ");
        vsb_cat(sb, "programs.\n *\n * XXX: When this file is changed, lib/");
        vsb_cat(sb, "libvcl/vcc_gen_fixed_token.tcl\n");
        vsb_cat(sb, " * XXX: *MUST* be rerun.\n */\n");
@@ -322,7 +322,7 @@ vcl_output_lang_h(struct vsb *sb)
 
        /* ../../include/vrt_obj.h */
 
-       vsb_cat(sb, "/*\n * $Id: vcc_gen_obj.tcl 3781 2009-02-17 10:29:20Z ");
+       vsb_cat(sb, "/*\n * $Id: vcc_gen_obj.tcl 3834 2009-02-27 12:02:50Z ");
        vsb_cat(sb, "phk $\n *\n * NB:  This file is machine generated, DO ");
        vsb_cat(sb, "NOT EDIT!\n *\n * Edit vcc_gen_obj.tcl instead\n");
        vsb_cat(sb, " */\n\nstruct sockaddr * VRT_r_client_ip(const struct ");
@@ -354,25 +354,31 @@ vcl_output_lang_h(struct vsb *sb)
        vsb_cat(sb, "*);\nvoid VRT_l_bereq_first_byte_timeout(struct sess *");
        vsb_cat(sb, ", double);\ndouble VRT_r_bereq_between_bytes_timeout(s");
        vsb_cat(sb, "truct sess *);\nvoid VRT_l_bereq_between_bytes_timeout");
-       vsb_cat(sb, "(struct sess *, double);\nconst char * VRT_r_beresp_re");
-       vsb_cat(sb, "quest(const struct sess *);\nvoid VRT_l_beresp_request");
-       vsb_cat(sb, "(const struct sess *, const char *, ...);\n");
-       vsb_cat(sb, "const char * VRT_r_beresp_url(const struct sess *);\n");
-       vsb_cat(sb, "void VRT_l_beresp_url(const struct sess *, const char ");
-       vsb_cat(sb, "*, ...);\nconst char * VRT_r_beresp_proto(const struct");
-       vsb_cat(sb, " sess *);\nvoid VRT_l_beresp_proto(const struct sess *");
-       vsb_cat(sb, ", const char *, ...);\nconst char * VRT_r_obj_proto(co");
-       vsb_cat(sb, "nst struct sess *);\nvoid VRT_l_obj_proto(const struct");
-       vsb_cat(sb, " sess *, const char *, ...);\nint VRT_r_obj_status(con");
-       vsb_cat(sb, "st struct sess *);\nvoid VRT_l_obj_status(const struct");
-       vsb_cat(sb, " sess *, int);\nconst char * VRT_r_obj_response(const ");
-       vsb_cat(sb, "struct sess *);\nvoid VRT_l_obj_response(const struct ");
-       vsb_cat(sb, "sess *, const char *, ...);\nint VRT_r_obj_hits(const ");
-       vsb_cat(sb, "struct sess *);\nunsigned VRT_r_obj_cacheable(const st");
-       vsb_cat(sb, "ruct sess *);\nvoid VRT_l_obj_cacheable(const struct s");
-       vsb_cat(sb, "ess *, unsigned);\ndouble VRT_r_obj_ttl(const struct s");
-       vsb_cat(sb, "ess *);\nvoid VRT_l_obj_ttl(const struct sess *, doubl");
-       vsb_cat(sb, "e);\ndouble VRT_r_obj_grace(const struct sess *);\n");
+       vsb_cat(sb, "(struct sess *, double);\nconst char * VRT_r_beresp_pr");
+       vsb_cat(sb, "oto(const struct sess *);\nvoid VRT_l_beresp_proto(con");
+       vsb_cat(sb, "st struct sess *, const char *, ...);\n");
+       vsb_cat(sb, "int VRT_r_beresp_status(const struct sess *);\n");
+       vsb_cat(sb, "void VRT_l_beresp_status(const struct sess *, int);\n");
+       vsb_cat(sb, "const char * VRT_r_beresp_response(const struct sess *");
+       vsb_cat(sb, ");\nvoid VRT_l_beresp_response(const struct sess *, co");
+       vsb_cat(sb, "nst char *, ...);\nunsigned VRT_r_beresp_cacheable(con");
+       vsb_cat(sb, "st struct sess *);\nvoid VRT_l_beresp_cacheable(const ");
+       vsb_cat(sb, "struct sess *, unsigned);\ndouble VRT_r_beresp_ttl(con");
+       vsb_cat(sb, "st struct sess *);\nvoid VRT_l_beresp_ttl(const struct");
+       vsb_cat(sb, " sess *, double);\ndouble VRT_r_beresp_grace(const str");
+       vsb_cat(sb, "uct sess *);\nvoid VRT_l_beresp_grace(const struct ses");
+       vsb_cat(sb, "s *, double);\nconst char * VRT_r_obj_proto(const stru");
+       vsb_cat(sb, "ct sess *);\nvoid VRT_l_obj_proto(const struct sess *,");
+       vsb_cat(sb, " const char *, ...);\nint VRT_r_obj_status(const struc");
+       vsb_cat(sb, "t sess *);\nvoid VRT_l_obj_status(const struct sess *,");
+       vsb_cat(sb, " int);\nconst char * VRT_r_obj_response(const struct s");
+       vsb_cat(sb, "ess *);\nvoid VRT_l_obj_response(const struct sess *, ");
+       vsb_cat(sb, "const char *, ...);\nint VRT_r_obj_hits(const struct s");
+       vsb_cat(sb, "ess *);\nunsigned VRT_r_obj_cacheable(const struct ses");
+       vsb_cat(sb, "s *);\nvoid VRT_l_obj_cacheable(const struct sess *, u");
+       vsb_cat(sb, "nsigned);\ndouble VRT_r_obj_ttl(const struct sess *);\n");
+       vsb_cat(sb, "void VRT_l_obj_ttl(const struct sess *, double);\n");
+       vsb_cat(sb, "double VRT_r_obj_grace(const struct sess *);\n");
        vsb_cat(sb, "void VRT_l_obj_grace(const struct sess *, double);\n");
        vsb_cat(sb, "double VRT_r_obj_lastuse(const struct sess *);\n");
        vsb_cat(sb, "const char * VRT_r_obj_hash(const struct sess *);\n");
index 2f5b18af308380c3548437cc6c55ccc16036c8ea..662650707efbe74e987e7d367066a2a2f66bef6f 100755 (executable)
@@ -146,81 +146,97 @@ set spobj {
 
     #######################################################################
     # Response from the backend
-    { beresp.request
+    { beresp.proto
        RW STRING
        {                             fetch                        }
        "const struct sess *"
     }
-    { beresp.url
-       RW STRING
+    { beresp.status
+       RW INT
        {                             fetch                        }
        "const struct sess *"
     }
-    { beresp.proto
+    { beresp.response
        RW STRING
        {                             fetch                        }
        "const struct sess *"
     }
     { beresp.http.
-       RW HDR_BEREQ
+       RW HDR_BERESP
        {                             fetch                        }
        "const struct sess *"
     }
+    { beresp.cacheable
+       RW BOOL
+       {                             fetch                              }
+       "const struct sess *"
+    }
+    { beresp.ttl
+       RW TIME
+       {                             fetch                              }
+       "const struct sess *"
+    }
+    { beresp.grace
+       RW TIME
+       {                             fetch                              }
+       "const struct sess *"
+    }
 
     #######################################################################
     # The (possibly) cached object
     { obj.proto
        RW STRING
-       {                         hit fetch                         error}
+       {                         hit                               error}
        "const struct sess *"
     }
     { obj.status
        RW INT
-       {                             fetch                         error}
+       {                                                           error}
        "const struct sess *"
     }
     { obj.response
        RW STRING
-       {                             fetch                         error}
+       {                                                           error}
        "const struct sess *"
     }
     { obj.hits
        RO INT
-       {                         hit fetch deliver                      }
+       {                         hit       deliver                      }
        "const struct sess *"
     }
     { obj.http.
        RW HDR_OBJ
-       {                         hit fetch                         error}
+       {                         hit                               error}
        "const struct sess *"
     }
 
     { obj.cacheable
        RW BOOL
-       {                         hit fetch         discard timeout error}
+       {                         hit                                    }
        "const struct sess *"
     }
     { obj.ttl
        RW TIME
-       {                         hit fetch         discard timeout error}
+       {                         hit               discard timeout error}
        "const struct sess *"
     }
     { obj.grace
        RW TIME
-       {                         hit fetch         discard timeout error}
+       {                         hit               discard timeout error}
        "const struct sess *"
     }
     { obj.lastuse
        RO TIME
-       {                         hit fetch deliver discard timeout error}
+       {                         hit       deliver discard timeout error}
        "const struct sess *"
     }
     { obj.hash
        RO STRING
-       {                    miss hit fetch deliver                 error}
+       {                    miss hit       deliver                 error}
        "const struct sess *"
     }
 
+    #######################################################################
     # The response we send back
     { resp.proto
        RW STRING
index 74f1391a4312a99254d145ef6f98545afc38787d..f57b4724370585b698dbf93a0af12f50d586d36d 100644 (file)
@@ -123,80 +123,91 @@ struct var vcc_vars[] = {
            V_RW,           0,
            VCL_MET_PASS | VCL_MET_MISS
        },
-       { "beresp.request", STRING, 14,
-           "VRT_r_beresp_request(sp)",     "VRT_l_beresp_request(sp, ",
+       { "beresp.proto", STRING, 12,
+           "VRT_r_beresp_proto(sp)",       "VRT_l_beresp_proto(sp, ",
            V_RW,           0,
            VCL_MET_FETCH
        },
-       { "beresp.url", STRING, 10,
-           "VRT_r_beresp_url(sp)",         "VRT_l_beresp_url(sp, ",
+       { "beresp.status", INT, 13,
+           "VRT_r_beresp_status(sp)",      "VRT_l_beresp_status(sp, ",
            V_RW,           0,
            VCL_MET_FETCH
        },
-       { "beresp.proto", STRING, 12,
-           "VRT_r_beresp_proto(sp)",       "VRT_l_beresp_proto(sp, ",
+       { "beresp.response", STRING, 15,
+           "VRT_r_beresp_response(sp)",            "VRT_l_beresp_response(sp, ",
            V_RW,           0,
            VCL_MET_FETCH
        },
        { "beresp.http.", HEADER, 12,
            "VRT_r_beresp_http_(sp)",       "VRT_l_beresp_http_(sp, ",
-           V_RW,           "HDR_BEREQ",
+           V_RW,           "HDR_BERESP",
+           VCL_MET_FETCH
+       },
+       { "beresp.cacheable", BOOL, 16,
+           "VRT_r_beresp_cacheable(sp)",           "VRT_l_beresp_cacheable(sp, ",
+           V_RW,           0,
+           VCL_MET_FETCH
+       },
+       { "beresp.ttl", TIME, 10,
+           "VRT_r_beresp_ttl(sp)",         "VRT_l_beresp_ttl(sp, ",
+           V_RW,           0,
+           VCL_MET_FETCH
+       },
+       { "beresp.grace", TIME, 12,
+           "VRT_r_beresp_grace(sp)",       "VRT_l_beresp_grace(sp, ",
+           V_RW,           0,
            VCL_MET_FETCH
        },
        { "obj.proto", STRING, 9,
            "VRT_r_obj_proto(sp)",          "VRT_l_obj_proto(sp, ",
            V_RW,           0,
-           VCL_MET_HIT | VCL_MET_FETCH | VCL_MET_ERROR
+           VCL_MET_HIT | VCL_MET_ERROR
        },
        { "obj.status", INT, 10,
            "VRT_r_obj_status(sp)",         "VRT_l_obj_status(sp, ",
            V_RW,           0,
-           VCL_MET_FETCH | VCL_MET_ERROR
+           VCL_MET_ERROR
        },
        { "obj.response", STRING, 12,
            "VRT_r_obj_response(sp)",       "VRT_l_obj_response(sp, ",
            V_RW,           0,
-           VCL_MET_FETCH | VCL_MET_ERROR
+           VCL_MET_ERROR
        },
        { "obj.hits", INT, 8,
            "VRT_r_obj_hits(sp)",           NULL,
            V_RO,           0,
-           VCL_MET_HIT | VCL_MET_FETCH | VCL_MET_DELIVER
+           VCL_MET_HIT | VCL_MET_DELIVER
        },
        { "obj.http.", HEADER, 9,
            "VRT_r_obj_http_(sp)",          "VRT_l_obj_http_(sp, ",
            V_RW,           "HDR_OBJ",
-           VCL_MET_HIT | VCL_MET_FETCH | VCL_MET_ERROR
+           VCL_MET_HIT | VCL_MET_ERROR
        },
        { "obj.cacheable", BOOL, 13,
            "VRT_r_obj_cacheable(sp)",      "VRT_l_obj_cacheable(sp, ",
            V_RW,           0,
-           VCL_MET_HIT | VCL_MET_FETCH | VCL_MET_DISCARD | VCL_MET_TIMEOUT
-            | VCL_MET_ERROR
+           VCL_MET_HIT
        },
        { "obj.ttl", TIME, 7,
            "VRT_r_obj_ttl(sp)",            "VRT_l_obj_ttl(sp, ",
            V_RW,           0,
-           VCL_MET_HIT | VCL_MET_FETCH | VCL_MET_DISCARD | VCL_MET_TIMEOUT
-            | VCL_MET_ERROR
+           VCL_MET_HIT | VCL_MET_DISCARD | VCL_MET_TIMEOUT | VCL_MET_ERROR
        },
        { "obj.grace", TIME, 9,
            "VRT_r_obj_grace(sp)",          "VRT_l_obj_grace(sp, ",
            V_RW,           0,
-           VCL_MET_HIT | VCL_MET_FETCH | VCL_MET_DISCARD | VCL_MET_TIMEOUT
-            | VCL_MET_ERROR
+           VCL_MET_HIT | VCL_MET_DISCARD | VCL_MET_TIMEOUT | VCL_MET_ERROR
        },
        { "obj.lastuse", TIME, 11,
            "VRT_r_obj_lastuse(sp)",        NULL,
            V_RO,           0,
-           VCL_MET_HIT | VCL_MET_FETCH | VCL_MET_DELIVER | VCL_MET_DISCARD
-            | VCL_MET_TIMEOUT | VCL_MET_ERROR
+           VCL_MET_HIT | VCL_MET_DELIVER | VCL_MET_DISCARD | VCL_MET_TIMEOUT
+            | VCL_MET_ERROR
        },
        { "obj.hash", STRING, 8,
            "VRT_r_obj_hash(sp)",           NULL,
            V_RO,           0,
-           VCL_MET_MISS | VCL_MET_HIT | VCL_MET_FETCH | VCL_MET_DELIVER
-            | VCL_MET_ERROR
+           VCL_MET_MISS | VCL_MET_HIT | VCL_MET_DELIVER | VCL_MET_ERROR
        },
        { "resp.proto", STRING, 10,
            "VRT_r_resp_proto(sp)",         "VRT_l_resp_proto(sp, ",