Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
libvmod-esiextra
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
uplex-varnish
libvmod-esiextra
Commits
ccf64cb8
Commit
ccf64cb8
authored
Nov 05, 2017
by
Nils Goroll
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Last-Modified support and ETag integration in test
parent
34044a00
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
207 additions
and
41 deletions
+207
-41
vmod_esiextra.c
src/vmod_esiextra.c
+102
-0
vmod_esiextra.vcc
src/vmod_esiextra.vcc
+14
-0
esi_recursive_full.vtc
src/vtc/esi_recursive_full.vtc
+74
-41
vmod_esiextra.vtc
src/vtc/vmod_esiextra.vtc
+17
-0
No files found.
src/vmod_esiextra.c
View file @
ccf64cb8
#include "config.h"
#include <string.h>
#include <stdlib.h>
#include <cache/cache.h>
#include <vcl.h>
...
...
@@ -29,3 +32,102 @@ vmod_bodyhash(VRT_CTX, VCL_HEADER hdr)
if
(
Bodyhash_push
(
bo
->
vfc
,
hdr
->
what
)
==
NULL
)
VRT_fail
(
ctx
,
"bodyhash push failed"
);
}
/* ============================================================================
* Last-Modified for all of ESI
*/
/*
* so far this is not much more as the VRT_priv ID
*/
struct
vmod_esiextra_lm
{
unsigned
magic
;
#define VMOD_ESIEXTRA_LM_MAGIC 0x3188a965
const
char
*
vcl_name
;
};
VCL_VOID
__match_proto__
(
td_esiextra_lm__init
)
vmod_lm__init
(
VRT_CTX
,
struct
vmod_esiextra_lm
**
lmobj
,
const
char
*
vcl_name
)
{
struct
vmod_esiextra_lm
*
o
;
assert
(
sizeof
(
void
*
)
>=
sizeof
(
VCL_TIME
));
CHECK_OBJ_NOTNULL
(
ctx
,
VRT_CTX_MAGIC
);
AN
(
lmobj
);
AZ
(
*
lmobj
);
ALLOC_OBJ
(
o
,
VMOD_ESIEXTRA_LM_MAGIC
);
AN
(
o
);
*
lmobj
=
o
;
o
->
vcl_name
=
vcl_name
;
AN
(
*
lmobj
);
}
VCL_VOID
__match_proto__
(
td_esiextra_lm__fini
)
vmod_lm__fini
(
struct
vmod_esiextra_lm
**
lmobj
)
{
AN
(
lmobj
);
if
(
*
lmobj
==
NULL
)
return
;
FREE_OBJ
(
*
lmobj
);
*
lmobj
=
NULL
;
}
static
VCL_TIME
*
lm_time
(
VRT_CTX
,
const
struct
vmod_esiextra_lm
*
lmobj
)
{
struct
vmod_priv
*
priv
;
VCL_TIME
*
t
;
priv
=
VRT_priv_top
(
ctx
,
(
void
*
)
lmobj
);
AN
(
priv
);
t
=
(
VCL_TIME
*
)(
&
priv
->
priv
);
if
(
!
isnormal
(
*
t
))
*
t
=
0
.
0
;
return
(
t
);
}
static
inline
int
lm_bad_task
(
VRT_CTX
)
{
if
((
ctx
->
method
&
VCL_MET_TASK_C
)
==
0
)
{
VRT_fail
(
ctx
,
"lm object only usable in client context"
);
return
1
;
}
return
0
;
}
VCL_BOOL
__match_proto__
(
td_esiextra_lminspect
)
vmod_lm_inspect
(
VRT_CTX
,
struct
vmod_esiextra_lm
*
lmobj
,
VCL_TIME
t
)
{
VCL_TIME
*
lm
;
CHECK_OBJ_NOTNULL
(
ctx
,
VRT_CTX_MAGIC
);
if
(
lm_bad_task
(
ctx
))
return
(
0
);
lm
=
lm_time
(
ctx
,
lmobj
);
if
(
t
<=
*
lm
)
return
(
0
);
*
lm
=
t
;
return
(
1
);
}
VCL_VOID
__match_proto__
(
td_esiextra_lmupdate
)
vmod_lm_update
(
VRT_CTX
,
struct
vmod_esiextra_lm
*
lmobj
,
VCL_TIME
t
)
{
(
void
)
vmod_lm_inspect
(
ctx
,
lmobj
,
t
);
}
VCL_TIME
__match_proto__
(
td_esiextra_lmget
)
vmod_lm_get
(
VRT_CTX
,
struct
vmod_esiextra_lm
*
lmobj
)
{
VCL_TIME
*
lm
;
CHECK_OBJ_NOTNULL
(
ctx
,
VRT_CTX_MAGIC
);
if
(
lm_bad_task
(
ctx
))
return
(
0
);
lm
=
lm_time
(
ctx
,
lmobj
);
return
(
*
lm
);
}
src/vmod_esiextra.vcc
View file @
ccf64cb8
...
...
@@ -12,6 +12,20 @@ $Function VOID bodyhash(HEADER)
Hash the received body.
$Object lm()
$Method BOOL .inspect(TIME)
Inspect time vs. saved time. If new time is after saved time, update
and return true. Otherwise return false.
$Method VOID .update(TIME)
same as inspect without a return value.
$Method TIME .get()
get the saved time.
SEE ALSO
========
...
...
src/vtc/esi_recursive_full.vtc
View file @
ccf64cb8
...
...
@@ -2,7 +2,9 @@ varnishtest "Test resp_top.* in an ESI context"
server s1 {
rxreq
txresp -body {
txresp \
-hdr "Last-Modified: Thu, 02 Nov 2017 18:38:02 GMT" \
-body {
<html>
Before include
<esi:include
src=
"/a"
/>
...
...
@@ -13,37 +15,45 @@ server s1 {
rxreq
expect req.url == "/a1"
txresp -body {
txresp \
-hdr "Last-Modified: Fri, 03 Nov 2017 18:38:03 GMT" \
-body {
Included file
<esi:include
src=
"/c"
/>
}
rxreq
expect req.url == "/c2"
txresp
txresp \
-hdr "Last-Modified: Sat, 04 Nov 2017 18:38:04 GMT" \
-body { c}
rxreq
expect req.url == "/b1"
txresp
txresp \
-hdr "Last-Modified: Sun, 05 Nov 2017 18:38:05 GMT" \
-body { b}
rxreq
expect req.url == "/noinclude"
txresp \
-hdr "Last-Modified: Fri, 03 Nov 2017 18:38:04 GMT" \
-body {
<html></html>
}
} -start
varnish v1 -vcl+backend {} -start
varnish v1 -
arg "-p feature=+esi_disable_xml_check" -
vcl+backend {} -start
varnish v1 -vcl+backend {
import esiextra;
import std;
backend recursive {
.host = "${v1_addr}";
.port = "${v1_port}";
}
sub recv_test_runtime_access {
if (req.url == "/level0readrecv") {
set req.http.foo = resp_top.http.foo;
return (synth(200));
}
if (req.url == "/level0writerecv") {
set resp_top.http.foo = req.http.foo;
return (synth(200));
}
sub vcl_init {
new esilm = esiextra.lm();
}
sub vcl_recv {
if (req.restarts == 0) {
...
...
@@ -55,13 +65,13 @@ varnish v1 -vcl+backend {
return (hash);
}
call recv_test_runtime_access;
if (req.http.X-Do-Recurse) {
set req.hash_ignore_busy = true;
set req.backend_hint = recursive;
set req.esi = false;
}
if (req.http.X-Recursive) {
set req.hash_ignore_busy = true;
}
if (req.http.TE == "trailers" || req.http.TEFAIL) {
# We vary on X-TE to differenciate pre-rendered ESI
# output with trailers
...
...
@@ -85,14 +95,26 @@ varnish v1 -vcl+backend {
} else {
set resp_top.http.X-ESI = req.url;
}
# updating for level > 1 would just be a waste, only the
# last update wins anyway
if (req.esi_level == 1) {
if (esilm.inspect(std.time(resp.http.Last-Modified,
now - 10s))) {
set resp_top.http.Last-Modified = esilm.get();
}
} else {
esilm.update(std.time(resp.http.Last-Modified, now - 10s));
}
return (deliver);
}
sub vcl_deliver {
if (req.esi_level > 0) {
call deliver_esi;
}
esilm.update(std.time(resp.http.Last-Modified, now - 10s));
if (req.http.TE == "trailers") {
set resp.http.Trailer = "X-ESI";
set resp.http.Trailer = "X-ESI, Last-Modified";
set resp.http.X-ESI = req.url;
}
unset resp.http.Vary;
if (resp.http.hits) {
...
...
@@ -110,12 +132,20 @@ varnish v1 -vcl+backend {
}
}
sub vcl_backend_response {
set beresp.do_esi = true;
set beresp.http.Vary = "X-TE";
if (bereq.http.X-Do-Recurse) {
# The recursively fetched Variant has all the headers
unset bereq.http.X-TE;
unset beresp.http.ETag;
esiextra.bodyhash(beresp.http.ETag);
if (beresp.http.Trailer) {
set beresp.http.Trailer = beresp.http.Trailer +
", ETag";
} else {
set beresp.http.Trailer = "ETag";
}
}
set beresp.do_esi = true;
set beresp.http.Vary = "X-TE";
}
}
...
...
@@ -124,33 +154,24 @@ logexpect l1 -v v1 -g raw {
# expect * * VCL_Error {^resp_top.http.X-ESI not writable unless sending Trailers$}
} -start
client c1 {
txreq -url "/level0readrecv"
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
} -run
client c1 {
txreq -url "/level0writerecv"
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
} -run
client c1 {
txreq -hdr "TE: trailers"
rxresp
expect resp.status == 200
expect resp.bodylen == 81
expect resp.http.Trailer == "X-ESI"
expect resp.http.X-ESI == "/a1:/c2:/b1"
expect resp.bodylen == 85
expect resp.http.Trailer == "X-ESI, Last-Modified"
expect resp.http.X-ESI == "/:/a1:/c2:/b1"
expect resp.http.Last-Modified == "Sun, 05 Nov 2017 18:38:05 GMT"
expect resp.http.hits == "0"
txreq
rxresp
expect resp.status == 200
expect resp.bodylen == 8
1
expect resp.bodylen == 8
5
expect resp.http.Trailer ==
<undef>
expect resp.http.X-ESI == "/a1:/c2:/b1"
expect resp.http.X-ESI == "/:/a1:/c2:/b1"
expect resp.http.Last-Modified == "Sun, 05 Nov 2017 18:38:05 GMT"
expect resp.http.ETag == {"8fd5e543966b9d8c767b0eab658adcccddfe73a8f5bf3815dead2da979339024"}
expect resp.http.hits == "1,0"
# this fails at esi level 1 - body contains "503 VCL failed"
...
...
@@ -165,11 +186,23 @@ client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.bodylen == 8
1
expect resp.bodylen == 8
5
expect resp.http.Trailer ==
<undef>
expect resp.http.X-ESI == "/a1:/c2:/b1"
expect resp.http.X-ESI == "/:/a1:/c2:/b1"
expect resp.http.Last-Modified == "Sun, 05 Nov 2017 18:38:05 GMT"
expect resp.http.ETag == {"8fd5e543966b9d8c767b0eab658adcccddfe73a8f5bf3815dead2da979339024"}
expect resp.http.hits == "1,1"
} -run
# no esi include
txreq -url "/noinclude"
rxresp
expect resp.status == 200
expect resp.bodylen == 13
expect resp.http.Trailer ==
<undef>
expect resp.http.X-ESI == "/noinclude"
expect resp.http.Last-Modified == "Fri, 03 Nov 2017 18:38:04 GMT"
expect resp.http.ETag == {"b633a587c652d02386c4f16f8c6f6aab7352d97f16367c3c40576214372dd628"}
expect resp.http.hits == "0,0"
} -run
varnish v1 -expect esi_errors == 0
logexpect l1 -wait
src/vtc/vmod_esiextra.vtc
View file @
ccf64cb8
...
...
@@ -3,8 +3,19 @@ varnishtest "Generate an ETag as the hash of the received body"
server s1 {
rxreq
txresp -body "foo"
rxreq
txresp -nolen -hdr "Transfer-encoding: chunked"
chunked {f}
delay .2
chunked {o}
delay .2
chunked {o}
delay .2
chunkedlen 0
} -start
varnish v1 -vcl+backend {
import esiextra;
...
...
@@ -18,3 +29,9 @@ client c1 -repeat 3 {
rxresp
expect resp.http.ETag == {"2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"}
} -run
client c1 -repeat 3 {
txreq -url "/chunked"
rxresp
expect resp.http.ETag == {"2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"}
} -run
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