Any object, also errors, we receive from the backend will
go to vcl_fetch(), and can be cached if desired.
Any object we create, for instance if we cannot contact the
backend, will go to vcl_error() and will not be cached.
Technical details:
Implement VCL variable setting for booleans like obj.cacheable.
Remove obj.valid, only valid objects go to vcl_fetch now.
On fetch failure, drop the object and go to STP_ERROR with 503
Update testcase b00015.vtc accordingly.
git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@3044
d4fa192b-c00b-0410-8231-
f00ffab90ce4
unsigned response;
- unsigned valid;
unsigned cacheable;
unsigned busy;
switch (sp->handling) {
case VCL_RET_DELIVER:
break;
- case VCL_RET_ERROR:
- HSH_Deref(sp->obj);
- sp->obj = NULL;
- sp->step = STP_ERROR;
- return (0);
default:
INCOMPL();
}
if (sp->obj == NULL) {
HSH_Prealloc(sp);
sp->obj = sp->wrk->nobj;
+ sp->obj->xid = sp->xid;
+ sp->obj->entered = sp->t_req;
sp->wrk->nobj = NULL;
} else {
/* XXX: Null the headers ? */
i = Fetch(sp);
CHECK_OBJ_NOTNULL(sp->director, DIRECTOR_MAGIC);
- if (!i)
- RFC2616_cache_policy(sp, sp->obj->http); /* XXX -> VCL */
- else {
- http_PutStatus(sp->wrk, sp->fd, sp->obj->http, 503);
- http_PutProtocol(sp->wrk, sp->fd, sp->obj->http, "HTTP/1.1");
- http_PutResponse(sp->wrk, sp->fd, sp->obj->http,
- "Backend error");
+ if (i) {
+VSL(SLT_Debug, sp->fd, "Fetch = %d", i);
+ sp->err_code = 503;
+ sp->step = STP_ERROR;
+ VBE_free_bereq(sp->bereq);
+ sp->bereq = NULL;
+ sp->obj->ttl = 0;
+ sp->obj->cacheable = 0;
+ HSH_Unbusy(sp);
+ HSH_Deref(sp->obj);
+ sp->obj = NULL;
+ return (0);
}
+ RFC2616_cache_policy(sp, sp->obj->http); /* XXX -> VCL */
+
sp->err_code = http_GetStatus(sp->obj->http);
VCL_fetch_method(sp);
return (sp->obj->field); \
}
-VOBJ(unsigned, valid, valid)
VOBJ(unsigned, cacheable, cacheable)
/*--------------------------------------------------------------------*/
"}\n"
"\n"
"sub vcl_fetch {\n"
- " if (!obj.valid) {\n"
- " error obj.status;\n"
- " }\n"
" if (!obj.cacheable) {\n"
" pass;\n"
" }\n"
case 410: /* Gone */
case 404: /* Not Found */
sp->obj->cacheable = 1;
- sp->obj->valid = 1;
body = 1;
break;
default:
sp->obj->cacheable = 0;
- sp->obj->valid = 1; /* XXX ? */
body = 0;
break;
}
test "Check synthetic error page caching"
+
+# First test that an internally generated error is not cached
+
+varnish v1 -vcl {
+ backend foo {
+ .host = "127.0.0.2";
+ }
+} -start
+
+client c1 {
+ txreq -url "/"
+ rxresp
+ expect resp.status == 503
+ expect resp.http.X-varnish == "1001"
+} -run
+
+client c1 {
+ txreq -url "/"
+ rxresp
+ expect resp.status == 503
+ expect resp.http.X-varnish == "1002"
+} -run
+
+# Then check that an cacheable error from the backend is
+
server s1 {
rxreq
- txresp -status 503 -msg "Server Error"
+ txresp -status 302
} -start
-varnish v1 -vcl+backend { } -start
+varnish v1 -vcl+backend { }
client c1 {
txreq -url "/"
rxresp
- expect resp.status == 503
- # Disable this for now to not upset automatic scripts
- #txreq -url "/"
- #rxresp
- #expect resp.status == 503
+ expect resp.status == 302
+ expect resp.http.X-varnish == "1003"
+} -run
+
+server s1 -wait
+
+client c1 {
+ txreq -url "/"
+ rxresp
+ expect resp.status == 302
+ expect resp.http.X-varnish == "1004 1003"
+} -run
+
+# Then check that a non-cacheable error from the backend can be
+
+server s1 {
+ rxreq
+ txresp -status 502
+} -start
+
+varnish v1 -vcl+backend {
+ sub vcl_fetch {
+ if (obj.status == 502) {
+ set obj.cacheable = true;
+ set obj.ttl = 10m;
+ }
+ }
+ }
+
+client c1 {
+ txreq -url "/2"
+ rxresp
+ expect resp.status == 502
+ expect resp.http.X-varnish == "1005"
+} -run
+
+server s1 -wait
+
+client c1 {
+ txreq -url "/2"
+ rxresp
+ expect resp.status == 502
+ expect resp.http.X-varnish == "1006 1005"
} -run
void VRT_l_obj_status(const struct sess *, int);
const char * VRT_r_obj_response(const struct sess *);
void VRT_l_obj_response(const struct sess *, const char *, ...);
-unsigned VRT_r_obj_valid(const struct sess *);
-void VRT_l_obj_valid(const struct sess *, unsigned);
unsigned VRT_r_obj_cacheable(const struct sess *);
void VRT_l_obj_cacheable(const struct sess *, unsigned);
double VRT_r_obj_ttl(const struct sess *);
}
Fb(tl, 0, "vrt_magic_string_end);\n");
break;
+ case BOOL:
+ if (tl->t->tok != '=') {
+ illegal_assignment(tl, "boolean");
+ return;
+ }
+ vcc_NextToken(tl);
+ ExpectErr(tl, ID);
+ if (vcc_IdIs(tl->t, "true")) {
+ Fb(tl, 0, " 1);\n", vp->lname);
+ } else if (vcc_IdIs(tl->t, "false")) {
+ Fb(tl, 0, " 0);\n", vp->lname);
+ } else {
+ vsb_printf(tl->sb,
+ "Expected true or false\n");
+ vcc_ErrWhere(tl, tl->t);
+ return;
+ }
+ vcc_NextToken(tl);
+ break;
default:
vsb_printf(tl->sb,
- "Assignments not possible for '%s'\n", vp->name);
+ "Assignments not possible for type of '%s'\n", vp->name);
vcc_ErrWhere(tl, tl->t);
return;
}
"const struct sess *"
}
- { obj.valid
- RW BOOL
- { hit fetch discard timeout error}
- "const struct sess *"
- }
{ obj.cacheable
RW BOOL
{ hit fetch discard timeout error}
"HDR_OBJ",
VCL_MET_HIT | VCL_MET_FETCH | VCL_MET_ERROR
},
- { "obj.valid", BOOL, 9,
- "VRT_r_obj_valid(sp)",
- "VRT_l_obj_valid(sp, ",
- V_RW,
- 0,
- VCL_MET_HIT | VCL_MET_FETCH | VCL_MET_DISCARD | VCL_MET_TIMEOUT | VCL_MET_ERROR
- },
{ "obj.cacheable", BOOL, 13,
"VRT_r_obj_cacheable(sp)",
"VRT_l_obj_cacheable(sp, ",