Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
varnish-cache
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
varnishcache
varnish-cache
Commits
d1241323
Commit
d1241323
authored
Jun 16, 2013
by
Poul-Henning Kamp
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Synthesize a 503 when we fail to fetch, and pass it on.
parent
cfbc1691
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
101 additions
and
89 deletions
+101
-89
cache_fetch.c
bin/varnishd/cache/cache_fetch.c
+68
-67
b00015.vtc
bin/varnishtest/tests/b00015.vtc
+26
-7
c00024.vtc
bin/varnishtest/tests/c00024.vtc
+3
-14
steps.h
include/tbl/steps.h
+4
-1
No files found.
bin/varnishd/cache/cache_fetch.c
View file @
d1241323
...
@@ -486,7 +486,8 @@ vbf_fetch_body(struct worker *wrk, void *priv)
...
@@ -486,7 +486,8 @@ vbf_fetch_body(struct worker *wrk, void *priv)
CHECK_OBJ_NOTNULL
(
wrk
,
WORKER_MAGIC
);
CHECK_OBJ_NOTNULL
(
wrk
,
WORKER_MAGIC
);
CAST_OBJ_NOTNULL
(
bo
,
priv
,
BUSYOBJ_MAGIC
);
CAST_OBJ_NOTNULL
(
bo
,
priv
,
BUSYOBJ_MAGIC
);
CHECK_OBJ_NOTNULL
(
bo
->
vbc
,
VBC_MAGIC
);
htc
=
&
bo
->
htc
;
CHECK_OBJ_ORNULL
(
bo
->
vbc
,
VBC_MAGIC
);
obj
=
bo
->
fetch_obj
;
obj
=
bo
->
fetch_obj
;
CHECK_OBJ_NOTNULL
(
obj
,
OBJECT_MAGIC
);
CHECK_OBJ_NOTNULL
(
obj
,
OBJECT_MAGIC
);
CHECK_OBJ_NOTNULL
(
obj
->
http
,
HTTP_MAGIC
);
CHECK_OBJ_NOTNULL
(
obj
->
http
,
HTTP_MAGIC
);
...
@@ -500,7 +501,6 @@ vbf_fetch_body(struct worker *wrk, void *priv)
...
@@ -500,7 +501,6 @@ vbf_fetch_body(struct worker *wrk, void *priv)
AZ
(
bo
->
stats
);
AZ
(
bo
->
stats
);
bo
->
stats
=
&
wrk
->
stats
;
bo
->
stats
=
&
wrk
->
stats
;
htc
=
&
bo
->
htc
;
if
(
bo
->
vfp
==
NULL
)
if
(
bo
->
vfp
==
NULL
)
bo
->
vfp
=
&
vfp_nop
;
bo
->
vfp
=
&
vfp_nop
;
...
@@ -513,7 +513,7 @@ vbf_fetch_body(struct worker *wrk, void *priv)
...
@@ -513,7 +513,7 @@ vbf_fetch_body(struct worker *wrk, void *priv)
/* XXX: pick up estimate from objdr ? */
/* XXX: pick up estimate from objdr ? */
cl
=
0
;
cl
=
0
;
cls
=
0
;
cls
=
bo
->
should_close
;
switch
(
htc
->
body_status
)
{
switch
(
htc
->
body_status
)
{
case
BS_NONE
:
case
BS_NONE
:
mklen
=
0
;
mklen
=
0
;
...
@@ -526,7 +526,7 @@ vbf_fetch_body(struct worker *wrk, void *priv)
...
@@ -526,7 +526,7 @@ vbf_fetch_body(struct worker *wrk, void *priv)
bo
->
vfp
->
begin
(
bo
,
cl
);
bo
->
vfp
->
begin
(
bo
,
cl
);
if
(
bo
->
state
==
BOS_FETCHING
&&
cl
>
0
)
if
(
bo
->
state
==
BOS_FETCHING
&&
cl
>
0
)
cls
=
vbf_fetch_straight
(
bo
,
htc
,
cl
);
cls
|
=
vbf_fetch_straight
(
bo
,
htc
,
cl
);
mklen
=
1
;
mklen
=
1
;
if
(
bo
->
vfp
->
end
(
bo
))
if
(
bo
->
vfp
->
end
(
bo
))
assert
(
bo
->
state
==
BOS_FAILED
);
assert
(
bo
->
state
==
BOS_FAILED
);
...
@@ -534,7 +534,7 @@ vbf_fetch_body(struct worker *wrk, void *priv)
...
@@ -534,7 +534,7 @@ vbf_fetch_body(struct worker *wrk, void *priv)
case
BS_CHUNKED
:
case
BS_CHUNKED
:
bo
->
vfp
->
begin
(
bo
,
cl
>
0
?
cl
:
0
);
bo
->
vfp
->
begin
(
bo
,
cl
>
0
?
cl
:
0
);
if
(
bo
->
state
==
BOS_FETCHING
)
if
(
bo
->
state
==
BOS_FETCHING
)
cls
=
vbf_fetch_chunked
(
bo
,
htc
);
cls
|
=
vbf_fetch_chunked
(
bo
,
htc
);
mklen
=
1
;
mklen
=
1
;
if
(
bo
->
vfp
->
end
(
bo
))
if
(
bo
->
vfp
->
end
(
bo
))
assert
(
bo
->
state
==
BOS_FAILED
);
assert
(
bo
->
state
==
BOS_FAILED
);
...
@@ -549,11 +549,10 @@ vbf_fetch_body(struct worker *wrk, void *priv)
...
@@ -549,11 +549,10 @@ vbf_fetch_body(struct worker *wrk, void *priv)
assert
(
bo
->
state
==
BOS_FAILED
);
assert
(
bo
->
state
==
BOS_FAILED
);
break
;
break
;
case
BS_ERROR
:
case
BS_ERROR
:
cls
=
VBF_Error
(
bo
,
"error incompatible Transfer-Encoding"
);
cls
|
=
VBF_Error
(
bo
,
"error incompatible Transfer-Encoding"
);
mklen
=
0
;
mklen
=
0
;
break
;
break
;
default:
default:
cls
=
0
;
mklen
=
0
;
mklen
=
0
;
INCOMPL
();
INCOMPL
();
}
}
...
@@ -574,18 +573,21 @@ vbf_fetch_body(struct worker *wrk, void *priv)
...
@@ -574,18 +573,21 @@ vbf_fetch_body(struct worker *wrk, void *priv)
http_Teardown
(
bo
->
bereq
);
http_Teardown
(
bo
->
bereq
);
http_Teardown
(
bo
->
beresp
);
http_Teardown
(
bo
->
beresp
);
if
(
bo
->
vbc
!=
NULL
)
{
if
(
cls
)
VDI_CloseFd
(
&
bo
->
vbc
);
else
VDI_RecycleFd
(
&
bo
->
vbc
);
}
if
(
bo
->
state
==
BOS_FAILED
)
{
if
(
bo
->
state
==
BOS_FAILED
)
{
wrk
->
stats
.
fetch_failed
++
;
wrk
->
stats
.
fetch_failed
++
;
VDI_CloseFd
(
&
bo
->
vbc
);
obj
->
len
=
0
;
obj
->
len
=
0
;
EXP_Clr
(
&
obj
->
exp
);
EXP_Clr
(
&
obj
->
exp
);
EXP_Rearm
(
obj
);
EXP_Rearm
(
obj
);
}
else
{
}
else
{
assert
(
bo
->
state
==
BOS_FETCHING
);
assert
(
bo
->
state
==
BOS_FETCHING
);
if
(
cls
==
0
&&
bo
->
should_close
)
cls
=
1
;
VSLb
(
bo
->
vsl
,
SLT_Length
,
"%zd"
,
obj
->
len
);
VSLb
(
bo
->
vsl
,
SLT_Length
,
"%zd"
,
obj
->
len
);
{
{
...
@@ -609,12 +611,6 @@ vbf_fetch_body(struct worker *wrk, void *priv)
...
@@ -609,12 +611,6 @@ vbf_fetch_body(struct worker *wrk, void *priv)
"Content-Length: %zd"
,
obj
->
len
);
"Content-Length: %zd"
,
obj
->
len
);
}
}
if
(
cls
)
VDI_CloseFd
(
&
bo
->
vbc
);
else
VDI_RecycleFd
(
&
bo
->
vbc
);
/* XXX: Atomic assignment, needs volatile/membar ? */
/* XXX: Atomic assignment, needs volatile/membar ? */
bo
->
state
=
BOS_FINISHED
;
bo
->
state
=
BOS_FINISHED
;
}
}
...
@@ -627,15 +623,14 @@ vbf_fetch_body(struct worker *wrk, void *priv)
...
@@ -627,15 +623,14 @@ vbf_fetch_body(struct worker *wrk, void *priv)
* Copy req->bereq and run it by VCL::vcl_backend_fetch{}
* Copy req->bereq and run it by VCL::vcl_backend_fetch{}
*/
*/
static
void
static
enum
fetch_step
vbf_
make_bereq
(
struct
worker
*
wrk
,
const
struct
req
*
req
,
struct
busyobj
*
bo
)
vbf_
stp_mkbereq
(
struct
worker
*
wrk
,
struct
busyobj
*
bo
,
const
struct
req
*
req
)
{
{
int
i
;
int
i
;
CHECK_OBJ_NOTNULL
(
wrk
,
WORKER_MAGIC
);
CHECK_OBJ_NOTNULL
(
wrk
,
WORKER_MAGIC
);
CHECK_OBJ_NOTNULL
(
req
,
REQ_MAGIC
);
CHECK_OBJ_NOTNULL
(
req
,
REQ_MAGIC
);
CHECK_OBJ_NOTNULL
(
bo
,
BUSYOBJ_MAGIC
);
CHECK_OBJ_NOTNULL
(
bo
,
BUSYOBJ_MAGIC
);
CHECK_OBJ_NOTNULL
(
bo
->
fetch_objcore
,
OBJCORE_MAGIC
);
AN
(
bo
->
director
);
AN
(
bo
->
director
);
AZ
(
bo
->
vbc
);
AZ
(
bo
->
vbc
);
...
@@ -666,18 +661,54 @@ vbf_make_bereq(struct worker *wrk, const struct req *req, struct busyobj *bo)
...
@@ -666,18 +661,54 @@ vbf_make_bereq(struct worker *wrk, const struct req *req, struct busyobj *bo)
http_PrintfHeader
(
bo
->
bereq
,
http_PrintfHeader
(
bo
->
bereq
,
"X-Varnish: %u"
,
bo
->
vsl
->
wid
&
VSL_IDENTMASK
);
"X-Varnish: %u"
,
bo
->
vsl
->
wid
&
VSL_IDENTMASK
);
return
(
F_STP_FETCHHDR
);
}
}
/*--------------------------------------------------------------------
/*--------------------------------------------------------------------
*/
*/
static
void
static
enum
fetch_step
vbf_
proc_resp
(
struct
worker
*
wrk
,
struct
busyobj
*
bo
)
vbf_
stp_fetchhdr
(
struct
worker
*
wrk
,
struct
busyobj
*
bo
,
struct
req
**
reqp
)
{
{
int
i
;
int
i
;
CHECK_OBJ_NOTNULL
(
wrk
,
WORKER_MAGIC
);
AN
(
reqp
);
CHECK_OBJ_NOTNULL
((
*
reqp
),
REQ_MAGIC
);
CHECK_OBJ_NOTNULL
(
bo
,
BUSYOBJ_MAGIC
);
CHECK_OBJ_NOTNULL
(
bo
,
BUSYOBJ_MAGIC
);
xxxassert
(
wrk
->
handling
==
VCL_RET_FETCH
);
HTTP_Setup
(
bo
->
beresp
,
bo
->
ws
,
bo
->
vsl
,
HTTP_Beresp
);
if
(
!
bo
->
do_pass
)
*
reqp
=
NULL
;
i
=
vbf_fetch_hdr
(
wrk
,
bo
,
*
reqp
);
/*
* If we recycle a backend connection, there is a finite chance
* that the backend closed it before we get a request to it.
* Do a single retry in that case.
*/
if
(
i
==
1
)
{
VSC_C_main
->
backend_retry
++
;
i
=
vbf_fetch_hdr
(
wrk
,
bo
,
*
reqp
);
}
if
(
bo
->
do_pass
)
*
reqp
=
NULL
;
if
(
i
)
{
AZ
(
bo
->
vbc
);
bo
->
err_code
=
503
;
http_SetH
(
bo
->
beresp
,
HTTP_HDR_PROTO
,
"HTTP/1.1"
);
http_SetResp
(
bo
->
beresp
,
"HTTP/1.1"
,
503
,
"Backend fetch failed"
);
http_SetHeader
(
bo
->
beresp
,
"Content-Length: 0"
);
http_SetHeader
(
bo
->
beresp
,
"Connection: close"
);
}
else
{
AN
(
bo
->
vbc
);
}
/*
/*
* These two headers can be spread over multiple actual headers
* These two headers can be spread over multiple actual headers
* and we rely on their content outside of VCL, so collect them
* and we rely on their content outside of VCL, so collect them
...
@@ -727,6 +758,7 @@ vbf_proc_resp(struct worker *wrk, struct busyobj *bo)
...
@@ -727,6 +758,7 @@ vbf_proc_resp(struct worker *wrk, struct busyobj *bo)
* no Content-Encoding --> object is not gzip'ed.
* no Content-Encoding --> object is not gzip'ed.
* anything else --> do nothing wrt gzip
* anything else --> do nothing wrt gzip
*
*
* XXX: BS_NONE/cl==0 should avoid gzip/gunzip
*/
*/
/* We do nothing unless the param is set */
/* We do nothing unless the param is set */
...
@@ -769,17 +801,18 @@ vbf_proc_resp(struct worker *wrk, struct busyobj *bo)
...
@@ -769,17 +801,18 @@ vbf_proc_resp(struct worker *wrk, struct busyobj *bo)
else
if
(
bo
->
is_gzip
)
else
if
(
bo
->
is_gzip
)
bo
->
vfp
=
&
vfp_testgzip
;
bo
->
vfp
=
&
vfp_testgzip
;
if
(
wrk
->
handling
!=
VCL_RET_DELIVER
)
return
(
F_STP_NOTYET
);
return
(
F_STP_FETCH
);
}
}
/*--------------------------------------------------------------------
/*--------------------------------------------------------------------
*/
*/
static
enum
fetch_step
static
enum
fetch_step
vbf_stp_fetch
(
struct
worker
*
wrk
,
struct
busyobj
*
bo
,
struct
req
**
reqp
)
vbf_stp_fetch
(
struct
worker
*
wrk
,
struct
busyobj
*
bo
)
{
{
int
i
;
struct
http
*
hp
,
*
hp2
;
struct
http
*
hp
,
*
hp2
;
struct
req
*
req
;
char
*
b
;
char
*
b
;
uint16_t
nhttp
;
uint16_t
nhttp
;
unsigned
l
;
unsigned
l
;
...
@@ -789,48 +822,10 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo, struct req **reqp)
...
@@ -789,48 +822,10 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo, struct req **reqp)
CHECK_OBJ_NOTNULL
(
wrk
,
WORKER_MAGIC
);
CHECK_OBJ_NOTNULL
(
wrk
,
WORKER_MAGIC
);
AN
(
reqp
);
req
=
*
reqp
;
CHECK_OBJ_NOTNULL
(
req
,
REQ_MAGIC
);
CHECK_OBJ_NOTNULL
(
bo
,
BUSYOBJ_MAGIC
);
CHECK_OBJ_NOTNULL
(
bo
,
BUSYOBJ_MAGIC
);
vbf_make_bereq
(
wrk
,
req
,
bo
);
if
(
wrk
->
handling
!=
VCL_RET_DELIVER
)
xxxassert
(
wrk
->
handling
==
VCL_RET_FETCH
);
VDI_CloseFd
(
&
bo
->
vbc
);
HTTP_Setup
(
bo
->
beresp
,
bo
->
ws
,
bo
->
vsl
,
HTTP_Beresp
);
if
(
!
bo
->
do_pass
)
{
AN
(
req
);
req
=
NULL
;
*
reqp
=
NULL
;
}
i
=
vbf_fetch_hdr
(
wrk
,
bo
,
req
);
/*
* If we recycle a backend connection, there is a finite chance
* that the backend closed it before we get a request to it.
* Do a single retry in that case.
*/
if
(
i
==
1
)
{
VSC_C_main
->
backend_retry
++
;
i
=
vbf_fetch_hdr
(
wrk
,
bo
,
req
);
}
if
(
bo
->
do_pass
)
{
AN
(
req
);
req
=
NULL
;
*
reqp
=
NULL
;
}
AZ
(
req
);
if
(
i
)
{
wrk
->
handling
=
VCL_RET_ERROR
;
bo
->
err_code
=
503
;
}
else
{
vbf_proc_resp
(
wrk
,
bo
);
if
(
wrk
->
handling
!=
VCL_RET_DELIVER
)
VDI_CloseFd
(
&
bo
->
vbc
);
}
if
(
wrk
->
handling
!=
VCL_RET_DELIVER
)
{
if
(
wrk
->
handling
!=
VCL_RET_DELIVER
)
{
/* Clean up partial fetch */
/* Clean up partial fetch */
...
@@ -1002,6 +997,12 @@ vbf_stp_abandon(struct worker *wrk, struct busyobj *bo)
...
@@ -1002,6 +997,12 @@ vbf_stp_abandon(struct worker *wrk, struct busyobj *bo)
/*--------------------------------------------------------------------
/*--------------------------------------------------------------------
*/
*/
static
enum
fetch_step
vbf_stp_notyet
(
void
)
{
WRONG
(
"Patience, grashopper, patience..."
);
}
static
enum
fetch_step
static
enum
fetch_step
vbf_stp_done
(
void
)
vbf_stp_done
(
void
)
{
{
...
@@ -1033,7 +1034,7 @@ vbf_fetch_thread(struct worker *wrk, void *priv)
...
@@ -1033,7 +1034,7 @@ vbf_fetch_thread(struct worker *wrk, void *priv)
bo
=
vsh
->
bo
;
bo
=
vsh
->
bo
;
THR_SetBusyobj
(
bo
);
THR_SetBusyobj
(
bo
);
bo
->
step
=
F_STP_
FETCH
;
bo
->
step
=
F_STP_
MKBEREQ
;
while
(
bo
->
step
!=
F_STP_DONE
)
{
while
(
bo
->
step
!=
F_STP_DONE
)
{
switch
(
bo
->
step
)
{
switch
(
bo
->
step
)
{
...
...
bin/varnishtest/tests/b00015.vtc
View file @
d1241323
...
@@ -15,36 +15,51 @@ client c1 {
...
@@ -15,36 +15,51 @@ client c1 {
expect resp.http.X-varnish == "1001"
expect resp.http.X-varnish == "1001"
} -run
} -run
delay .1
client c1 {
client c1 {
txreq -url "/"
txreq -url "/"
rxresp
rxresp
expect resp.status == 503
expect resp.status == 503
expect resp.http.X-varnish == "100
5
"
expect resp.http.X-varnish == "100
4
"
} -run
} -run
# Then check that an cacheable error from the backend is
delay .1
# Then check that a cacheable error from the backend is
varnish v1 -cliok "ban req.url ~ .*"
server s1 {
server s1 {
rxreq
rxreq
txresp -status 302
txresp -status 302
} -start
} -start
varnish v1 -vcl+backend { }
varnish v1 -vcl+backend {
sub vcl_backend_response {
set beresp.http.ttl = beresp.ttl;
set beresp.http.uncacheable = beresp.uncacheable;
}
}
client c1 {
client c1 {
txreq -url "/"
txreq -url "/"
rxresp
rxresp
expect resp.status == 302
expect resp.status == 302
expect resp.http.X-varnish == "100
9
"
expect resp.http.X-varnish == "100
7
"
} -run
} -run
delay .1
client c1 {
client c1 {
txreq -url "/"
txreq -url "/"
rxresp
rxresp
expect resp.status == 302
expect resp.status == 302
expect resp.http.X-varnish == "101
2 1010
"
expect resp.http.X-varnish == "101
0 1008
"
} -run
} -run
delay .1
# Then check that a non-cacheable error from the backend can be
# Then check that a non-cacheable error from the backend can be
server s1 {
server s1 {
...
@@ -64,12 +79,16 @@ client c1 {
...
@@ -64,12 +79,16 @@ client c1 {
txreq -url "/2"
txreq -url "/2"
rxresp
rxresp
expect resp.status == 502
expect resp.status == 502
expect resp.http.X-varnish == "101
4
"
expect resp.http.X-varnish == "101
2
"
} -run
} -run
delay .1
client c1 {
client c1 {
txreq -url "/2"
txreq -url "/2"
rxresp
rxresp
expect resp.status == 502
expect resp.status == 502
expect resp.http.X-varnish == "101
7 1015
"
expect resp.http.X-varnish == "101
5 1013
"
} -run
} -run
delay .1
bin/varnishtest/tests/c00024.vtc
View file @
d1241323
...
@@ -5,21 +5,10 @@ server s1 {
...
@@ -5,21 +5,10 @@ server s1 {
txresp
txresp
} -start
} -start
server s2 {
varnish v1 -vcl+backend {
} -start
varnish v1 -vcl {
backend bad {
.host = "${s2_addr}";
.port = "${s2_port}";
}
backend good {
.host = "${s1_addr}";
.port = "${s1_port}";
}
sub vcl_recv {
sub vcl_recv {
if (req.restarts
>
0) {
if (req.restarts
==
0) {
set req.backend = good
;
return (error(701, "FOO"))
;
}
}
}
}
sub vcl_error {
sub vcl_error {
...
...
include/tbl/steps.h
View file @
d1241323
...
@@ -50,8 +50,11 @@ REQ_STEP(error, ERROR, (wrk, req))
...
@@ -50,8 +50,11 @@ REQ_STEP(error, ERROR, (wrk, req))
#endif
#endif
#ifdef FETCH_STEP
#ifdef FETCH_STEP
FETCH_STEP
(
fetch
,
FETCH
,
(
wrk
,
bo
,
reqp
))
FETCH_STEP
(
mkbereq
,
MKBEREQ
,
(
wrk
,
bo
,
*
reqp
))
FETCH_STEP
(
fetchhdr
,
FETCHHDR
,
(
wrk
,
bo
,
reqp
))
FETCH_STEP
(
fetch
,
FETCH
,
(
wrk
,
bo
))
FETCH_STEP
(
abandon
,
ABANDON
,
(
wrk
,
bo
))
FETCH_STEP
(
abandon
,
ABANDON
,
(
wrk
,
bo
))
FETCH_STEP
(
notyet
,
NOTYET
,
())
FETCH_STEP
(
done
,
DONE
,
())
FETCH_STEP
(
done
,
DONE
,
())
#endif
#endif
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment