Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
libvmod-selector
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-selector
Commits
4aaec2ff
Commit
4aaec2ff
authored
Feb 22, 2021
by
Geoff Simmons
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add the .check_call() method.
parent
d6d30486
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
340 additions
and
41 deletions
+340
-41
README.rst
README.rst
+15
-0
associate.c
src/associate.c
+57
-29
match.c
src/match.c
+5
-5
subroutine.vtc
src/tests/subroutine.vtc
+249
-6
vmod_selector.h
src/vmod_selector.h
+8
-1
vmod_selector.vcc
src/vmod_selector.vcc
+6
-0
No files found.
README.rst
View file @
4aaec2ff
...
...
@@ -1072,6 +1072,21 @@ SUB xset.subroutine(INT n, STRING element, ENUM select)
XXX ...
.. _xset.check_call():
BOOL xset.check_call(INT n, STRING element, ENUM select)
--------------------------------------------------------
::
BOOL xset.check_call(
INT n=0,
STRING element=0,
ENUM {UNIQUE, EXACT, FIRST, LAST, SHORTEST, LONGEST} select=UNIQUE
)
XXX ...
.. _selector.version():
STRING version()
...
...
src/associate.c
View file @
4aaec2ff
...
...
@@ -31,11 +31,11 @@
static
unsigned
select
(
VRT_CTX
,
const
struct
match_data
*
const
restrict
match
,
const
char
*
const
restrict
obj
,
VCL_ENUM
const
restrict
selects
,
const
char
*
const
restrict
method
)
const
char
*
const
restrict
method
,
int
fail
)
{
if
(
selects
==
VENUM
(
EXACT
))
{
if
(
match
->
exact
==
UINT_MAX
)
VFAIL
(
ctx
,
"%s.%s(select=EXACT): "
VFAIL
_OR_NOTICE
(
ctx
,
fail
,
"%s.%s(select=EXACT): "
"no element matched exactly"
,
obj
,
method
);
return
match
->
exact
;
}
...
...
@@ -45,8 +45,9 @@ select(VRT_CTX, const struct match_data * const restrict match,
switch
(
selects
[
0
])
{
case
'U'
:
assert
(
selects
==
VENUM
(
UNIQUE
));
VFAIL
(
ctx
,
"%s.%s(select=UNIQUE): %d elements were matched"
,
obj
,
method
,
match
->
n
);
VFAIL_OR_NOTICE
(
ctx
,
fail
,
"%s.%s(select=UNIQUE): %d elements were matched"
,
obj
,
method
,
match
->
n
);
return
(
UINT_MAX
);
case
'L'
:
if
(
selects
==
VENUM
(
LAST
))
...
...
@@ -81,7 +82,7 @@ vmod_set_which(VRT_CTX, struct vmod_selector_set *set, VCL_ENUM selects,
return
(
UINT_MAX
);
}
match
=
get_existing_match_data
(
ctx
,
set
,
"which"
);
match
=
get_existing_match_data
(
ctx
,
set
,
"which"
,
1
);
if
(
element
!=
NULL
)
{
CHECK_OBJ_NOTNULL
(
match
,
MATCH_DATA_MAGIC
);
assert
(
match
->
n
==
1
);
...
...
@@ -89,35 +90,38 @@ vmod_set_which(VRT_CTX, struct vmod_selector_set *set, VCL_ENUM selects,
}
if
(
match
==
NULL
||
match
->
n
==
0
)
return
(
0
);
return
(
select
(
ctx
,
match
,
set
->
vcl_name
,
selects
,
"which"
)
+
1
);
return
(
select
(
ctx
,
match
,
set
->
vcl_name
,
selects
,
"which"
,
1
)
+
1
);
}
static
unsigned
get_idx
(
VRT_CTX
,
VCL_INT
n
,
const
struct
vmod_selector_set
*
const
restrict
set
,
const
char
*
const
restrict
method
,
VCL_STRING
const
restrict
element
,
VCL_ENUM
const
restrict
selects
)
VCL_ENUM
const
restrict
selects
,
int
fail
)
{
struct
match_data
*
match
;
if
(
n
>
0
)
{
if
(
n
>
set
->
nmembers
)
{
VFAIL
(
ctx
,
"%s.%s(%ld): set has %d elements"
,
set
->
vcl_name
,
method
,
n
,
set
->
nmembers
);
VFAIL_OR_NOTICE
(
ctx
,
fail
,
"%s.%s(%ld): set has %d elements"
,
set
->
vcl_name
,
method
,
n
,
set
->
nmembers
);
return
(
UINT_MAX
);
}
return
(
n
-
1
);
}
if
(
element
!=
NULL
)
if
(
!
vmod_set_match
(
ctx
,
TRUST_ME
(
set
),
element
))
{
VFAIL
(
ctx
,
"%s.%s(element=
\"
%s
\"
): no such element"
,
set
->
vcl_name
,
method
,
element
);
VFAIL_OR_NOTICE
(
ctx
,
fail
,
"%s.%s(element=
\"
%s
\"
): no such element"
,
set
->
vcl_name
,
method
,
element
);
return
(
UINT_MAX
);
}
match
=
get_existing_match_data
(
ctx
,
set
,
method
);
match
=
get_existing_match_data
(
ctx
,
set
,
method
,
fail
);
if
(
match
==
NULL
||
match
->
n
==
0
)
return
(
UINT_MAX
);
return
(
select
(
ctx
,
match
,
set
->
vcl_name
,
selects
,
method
));
return
(
select
(
ctx
,
match
,
set
->
vcl_name
,
selects
,
method
,
fail
));
}
VCL_STRING
...
...
@@ -129,7 +133,7 @@ vmod_set_element(VRT_CTX, struct vmod_selector_set *set, VCL_INT n,
CHECK_OBJ_NOTNULL
(
ctx
,
VRT_CTX_MAGIC
);
CHECK_OBJ_NOTNULL
(
set
,
VMOD_SELECTOR_SET_MAGIC
);
idx
=
get_idx
(
ctx
,
n
,
set
,
"element"
,
NULL
,
selects
);
idx
=
get_idx
(
ctx
,
n
,
set
,
"element"
,
NULL
,
selects
,
1
);
if
(
idx
==
UINT_MAX
)
return
(
NULL
);
return
(
set
->
members
[
idx
]);
...
...
@@ -139,11 +143,12 @@ static inline int
check_added
(
VRT_CTX
,
const
struct
vmod_selector_set
*
const
restrict
set
,
unsigned
idx
,
enum
bitmap_e
bitmap
,
const
char
*
const
restrict
method
,
const
char
*
const
restrict
type
)
const
char
*
const
restrict
type
,
int
fail
)
{
if
(
!
is_added
(
set
,
idx
,
bitmap
))
{
VFAIL
(
ctx
,
"%s.%s(): %s not added for element %u"
,
set
->
vcl_name
,
method
,
type
,
idx
+
1
);
VFAIL_OR_NOTICE
(
ctx
,
fail
,
"%s.%s(): %s not added for element %u"
,
set
->
vcl_name
,
method
,
type
,
idx
+
1
);
return
(
0
);
}
return
(
1
);
...
...
@@ -159,10 +164,10 @@ vmod_set_backend(VRT_CTX, struct vmod_selector_set *set, VCL_INT n,
CHECK_OBJ_NOTNULL
(
ctx
,
VRT_CTX_MAGIC
);
CHECK_OBJ_NOTNULL
(
set
,
VMOD_SELECTOR_SET_MAGIC
);
idx
=
get_idx
(
ctx
,
n
,
set
,
"backend"
,
element
,
selects
);
idx
=
get_idx
(
ctx
,
n
,
set
,
"backend"
,
element
,
selects
,
1
);
if
(
idx
==
UINT_MAX
)
return
(
NULL
);
if
(
!
check_added
(
ctx
,
set
,
idx
,
BACKEND
,
"backend"
,
"backend"
))
if
(
!
check_added
(
ctx
,
set
,
idx
,
BACKEND
,
"backend"
,
"backend"
,
1
))
return
(
NULL
);
b
=
set
->
table
[
idx
]
->
backend
;
...
...
@@ -180,10 +185,10 @@ vmod_set_string(VRT_CTX, struct vmod_selector_set * set, VCL_INT n,
CHECK_OBJ_NOTNULL
(
ctx
,
VRT_CTX_MAGIC
);
CHECK_OBJ_NOTNULL
(
set
,
VMOD_SELECTOR_SET_MAGIC
);
idx
=
get_idx
(
ctx
,
n
,
set
,
"string"
,
element
,
selects
);
idx
=
get_idx
(
ctx
,
n
,
set
,
"string"
,
element
,
selects
,
1
);
if
(
idx
==
UINT_MAX
)
return
(
NULL
);
if
(
!
check_added
(
ctx
,
set
,
idx
,
STRING
,
"string"
,
"string"
))
if
(
!
check_added
(
ctx
,
set
,
idx
,
STRING
,
"string"
,
"string"
,
1
))
return
(
NULL
);
s
=
set
->
table
[
idx
]
->
string
;
...
...
@@ -200,10 +205,10 @@ vmod_set_integer(VRT_CTX, struct vmod_selector_set * set, VCL_INT n,
CHECK_OBJ_NOTNULL
(
ctx
,
VRT_CTX_MAGIC
);
CHECK_OBJ_NOTNULL
(
set
,
VMOD_SELECTOR_SET_MAGIC
);
idx
=
get_idx
(
ctx
,
n
,
set
,
"integer"
,
element
,
selects
);
idx
=
get_idx
(
ctx
,
n
,
set
,
"integer"
,
element
,
selects
,
1
);
if
(
idx
==
UINT_MAX
)
return
(
0
);
if
(
!
check_added
(
ctx
,
set
,
idx
,
INTEGER
,
"integer"
,
"integer"
))
if
(
!
check_added
(
ctx
,
set
,
idx
,
INTEGER
,
"integer"
,
"integer"
,
1
))
return
(
0
);
return
(
set
->
table
[
idx
]
->
integer
);
...
...
@@ -220,10 +225,10 @@ get_re(VRT_CTX, const struct vmod_selector_set * const restrict set,
CHECK_OBJ_NOTNULL
(
ctx
,
VRT_CTX_MAGIC
);
CHECK_OBJ_NOTNULL
(
set
,
VMOD_SELECTOR_SET_MAGIC
);
idx
=
get_idx
(
ctx
,
n
,
set
,
method
,
element
,
selects
);
idx
=
get_idx
(
ctx
,
n
,
set
,
method
,
element
,
selects
,
1
);
if
(
idx
==
UINT_MAX
)
return
(
NULL
);
if
(
!
check_added
(
ctx
,
set
,
idx
,
REGEX
,
method
,
"regex"
))
if
(
!
check_added
(
ctx
,
set
,
idx
,
REGEX
,
method
,
"regex"
,
1
))
return
(
NULL
);
re
=
set
->
table
[
idx
]
->
re
;
...
...
@@ -265,10 +270,10 @@ vmod_set_bool(VRT_CTX, struct VPFX(selector_set) *set, VCL_INT n,
CHECK_OBJ_NOTNULL
(
ctx
,
VRT_CTX_MAGIC
);
CHECK_OBJ_NOTNULL
(
set
,
VMOD_SELECTOR_SET_MAGIC
);
idx
=
get_idx
(
ctx
,
n
,
set
,
"bool"
,
element
,
selects
);
idx
=
get_idx
(
ctx
,
n
,
set
,
"bool"
,
element
,
selects
,
1
);
if
(
idx
==
UINT_MAX
)
return
(
0
);
if
(
!
check_added
(
ctx
,
set
,
idx
,
BOOLEAN
,
"bool"
,
"boolean"
))
if
(
!
check_added
(
ctx
,
set
,
idx
,
BOOLEAN
,
"bool"
,
"boolean"
,
1
))
return
(
0
);
return
(
set
->
table
[
idx
]
->
bool
);
...
...
@@ -283,11 +288,34 @@ vmod_set_subroutine(VRT_CTX, struct VPFX(selector_set) *set, VCL_INT n,
CHECK_OBJ_NOTNULL
(
ctx
,
VRT_CTX_MAGIC
);
CHECK_OBJ_NOTNULL
(
set
,
VMOD_SELECTOR_SET_MAGIC
);
idx
=
get_idx
(
ctx
,
n
,
set
,
"subroutine"
,
element
,
selects
);
idx
=
get_idx
(
ctx
,
n
,
set
,
"subroutine"
,
element
,
selects
,
1
);
if
(
idx
==
UINT_MAX
)
return
(
NULL
);
if
(
!
check_added
(
ctx
,
set
,
idx
,
SUB
,
"subroutine"
,
"subroutine"
))
if
(
!
check_added
(
ctx
,
set
,
idx
,
SUB
,
"subroutine"
,
"subroutine"
,
1
))
return
(
NULL
);
return
(
set
->
table
[
idx
]
->
sub
);
}
VCL_BOOL
vmod_set_check_call
(
VRT_CTX
,
struct
VPFX
(
selector_set
)
*
set
,
VCL_INT
n
,
VCL_STRING
element
,
VCL_ENUM
selects
)
{
unsigned
idx
;
VCL_STRING
err
;
CHECK_OBJ_NOTNULL
(
ctx
,
VRT_CTX_MAGIC
);
CHECK_OBJ_NOTNULL
(
set
,
VMOD_SELECTOR_SET_MAGIC
);
idx
=
get_idx
(
ctx
,
n
,
set
,
"check_call"
,
element
,
selects
,
0
);
if
(
idx
==
UINT_MAX
)
return
(
0
);
if
(
!
check_added
(
ctx
,
set
,
idx
,
SUB
,
"check_call"
,
"subroutine"
,
0
))
return
(
0
);
if
((
err
=
VRT_check_call
(
ctx
,
set
->
table
[
idx
]
->
sub
))
!=
NULL
)
{
VNOTICE
(
ctx
,
"%s"
,
err
);
return
(
0
);
}
return
(
1
);
}
src/match.c
View file @
4aaec2ff
...
...
@@ -183,7 +183,7 @@ vmod_set_hasprefix(VRT_CTX, struct vmod_selector_set *set, VCL_STRING subject)
struct
match_data
*
get_existing_match_data
(
VRT_CTX
,
const
struct
vmod_selector_set
*
const
restrict
set
,
const
char
*
const
restrict
method
)
const
char
*
const
restrict
method
,
int
fail
)
{
struct
vmod_priv
*
task
;
struct
match_data
*
match
;
...
...
@@ -191,8 +191,8 @@ get_existing_match_data(VRT_CTX,
task
=
VRT_priv_task
(
ctx
,
set
);
AN
(
task
);
if
(
task
->
priv
==
NULL
)
{
VFAIL
(
ctx
,
"%s.%s() called without prior match"
,
set
->
vcl_name
,
method
);
VFAIL
_OR_NOTICE
(
ctx
,
fail
,
"%s.%s() called without prior match"
,
set
->
vcl_name
,
method
);
return
(
NULL
);
}
WS_Assert_Allocated
(
ctx
->
ws
,
task
->
priv
,
sizeof
(
*
match
));
...
...
@@ -208,7 +208,7 @@ vmod_set_nmatches(VRT_CTX, struct vmod_selector_set *set)
CHECK_OBJ_NOTNULL
(
ctx
,
VRT_CTX_MAGIC
);
CHECK_OBJ_NOTNULL
(
set
,
VMOD_SELECTOR_SET_MAGIC
);
match
=
get_existing_match_data
(
ctx
,
set
,
"nmatches"
);
match
=
get_existing_match_data
(
ctx
,
set
,
"nmatches"
,
1
);
if
(
match
==
NULL
)
return
(
0
);
return
(
match
->
n
);
...
...
@@ -229,7 +229,7 @@ vmod_set_matched(VRT_CTX, struct VPFX(selector_set) *set, VCL_INT idx,
return
(
0
);
}
match
=
get_existing_match_data
(
ctx
,
set
,
"matched"
);
match
=
get_existing_match_data
(
ctx
,
set
,
"matched"
,
1
);
if
(
match
==
NULL
||
match
->
n
==
0
)
return
(
0
);
...
...
src/tests/subroutine.vtc
View file @
4aaec2ff
# looks like -*- vcl -*-
varnishtest "
call() method
"
varnishtest "
.subroutine() and .check_call() methods
"
varnish v1 -vcl {
import ${vmod_selector};
...
...
@@ -65,6 +65,12 @@ varnish v1 -vcl {
}
sub vcl_synth {
set resp.http.Check-1 = s.check_call(1);
set resp.http.Check-2 = s.check_call(2);
set resp.http.Check-3 = s.check_call(3);
set resp.http.Check-4 = s.check_call(4);
set resp.http.Check-5 = s.check_call(5);
set resp.http.X = "N";
call s.subroutine(1);
call s.subroutine(2);
...
...
@@ -81,8 +87,25 @@ varnish v1 -vcl {
call s.subroutine(select=LAST);
call s.subroutine(select=SHORTEST);
call s.subroutine(select=LONGEST);
set resp.http.Check-Noarg = s.check_call();
set resp.http.Check-Unique
= s.check_call(select=UNIQUE);
set resp.http.Check-Exact = s.check_call(select=EXACT);
set resp.http.Check-First = s.check_call(select=FIRST);
set resp.http.Check-Last = s.check_call(select=LAST);
set resp.http.Check-Shortest
= s.check_call(select=SHORTEST);
set resp.http.Check-Longest
= s.check_call(select=LONGEST);
}
set resp.http.Check-Foo = s.check_call(element="foo");
set resp.http.Check-Bar = s.check_call(element="bar");
set resp.http.Check-Baz = s.check_call(element="baz");
set resp.http.Check-Quux = s.check_call(element="quux");
set resp.http.Check-Foobar = s.check_call(element="foobar");
set resp.http.X = "E";
call s.subroutine(element="foo");
call s.subroutine(element="bar");
...
...
@@ -90,6 +113,8 @@ varnish v1 -vcl {
call s.subroutine(element="quux");
call s.subroutine(element="foobar");
if (req.http.Element) {
set resp.http.Check-Element
= s.check_call(element=req.http.Element);
call s.subroutine(element=req.http.Element);
}
...
...
@@ -101,6 +126,18 @@ client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.Check-1 == true
expect resp.http.Check-2 == true
expect resp.http.Check-3 == true
expect resp.http.Check-4 == true
expect resp.http.Check-5 == true
expect resp.http.Check-Foo == true
expect resp.http.Check-Bar == true
expect resp.http.Check-Baz == true
expect resp.http.Check-Quux == true
expect resp.http.Check-Foobar == true
expect resp.http.Foo == "NE"
expect resp.http.Bar == "NE"
expect resp.http.Baz == "NE"
...
...
@@ -110,6 +147,14 @@ client c1 {
txreq -hdr "Word: foo"
rxresp
expect resp.status == 200
expect resp.http.Check-Noarg == true
expect resp.http.Check-Unique == true
expect resp.http.Check-Exact == true
expect resp.http.Check-First == true
expect resp.http.Check-Last == true
expect resp.http.Check-Longest == true
expect resp.http.Check-Shortest == true
expect resp.http.Foo == "NSSSSSSSE"
expect resp.http.Bar == "NE"
expect resp.http.Baz == "NE"
...
...
@@ -119,6 +164,14 @@ client c1 {
txreq -hdr "Word: bar"
rxresp
expect resp.status == 200
expect resp.http.Check-Noarg == true
expect resp.http.Check-Unique == true
expect resp.http.Check-Exact == true
expect resp.http.Check-First == true
expect resp.http.Check-Last == true
expect resp.http.Check-Longest == true
expect resp.http.Check-Shortest == true
expect resp.http.Foo == "NE"
expect resp.http.Bar == "NSSSSSSSE"
expect resp.http.Baz == "NE"
...
...
@@ -127,6 +180,14 @@ client c1 {
txreq -hdr "Word: baz"
rxresp
expect resp.http.Check-Noarg == true
expect resp.http.Check-Unique == true
expect resp.http.Check-Exact == true
expect resp.http.Check-First == true
expect resp.http.Check-Last == true
expect resp.http.Check-Longest == true
expect resp.http.Check-Shortest == true
expect resp.status == 200
expect resp.http.Foo == "NE"
expect resp.http.Bar == "NE"
...
...
@@ -136,6 +197,14 @@ client c1 {
txreq -hdr "Word: quux"
rxresp
expect resp.http.Check-Noarg == true
expect resp.http.Check-Unique == true
expect resp.http.Check-Exact == true
expect resp.http.Check-First == true
expect resp.http.Check-Last == true
expect resp.http.Check-Longest == true
expect resp.http.Check-Shortest == true
expect resp.status == 200
expect resp.http.Foo == "NE"
expect resp.http.Bar == "NE"
...
...
@@ -146,6 +215,14 @@ client c1 {
txreq -hdr "Word: foobar"
rxresp
expect resp.status == 200
expect resp.http.Check-Noarg == true
expect resp.http.Check-Unique == true
expect resp.http.Check-Exact == true
expect resp.http.Check-First == true
expect resp.http.Check-Last == true
expect resp.http.Check-Longest == true
expect resp.http.Check-Shortest == true
expect resp.http.Foo == "NE"
expect resp.http.Bar == "NE"
expect resp.http.Baz == "NE"
...
...
@@ -162,6 +239,12 @@ logexpect l1 -v v1 -d 1 -g vxid -q "Notice" {
expect 0 * Begin req
expect * = Notice {^vmod_selector: s\.match\(\): subject string is NULL$}
expect * = End
expect 0 * Begin req
expect * = Notice {^vmod_selector: s\.match\(\): subject string is NULL$}
expect * = Notice {^vmod_selector: s\.check_call\(element="oof"\): no such element$}
expect 0 = RespHeader {^Check-Element: false$}
expect * = End
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
...
...
@@ -178,23 +261,23 @@ varnish v1 -vcl {
backend b None;
sub foo {
set re
sp
.http.Called = "foo";
set re
q
.http.Called = "foo";
}
sub bar {
set re
sp
.http.Called = "bar";
set re
q
.http.Called = "bar";
}
sub baz {
set re
sp
.http.Called = "baz";
set re
q
.http.Called = "baz";
}
sub quux {
set re
sp
.http.Called = "quux";
set re
q
.http.Called = "quux";
}
sub foobar {
set re
sp
.http.Called = "foobar";
set re
q
.http.Called = "foobar";
}
sub vcl_init {
...
...
@@ -207,9 +290,18 @@ varnish v1 -vcl {
}
sub vcl_recv {
set req.http.Check-Call
= s.check_call(std.integer(req.http.Int));
call s.subroutine(std.integer(req.http.Int));
return (synth(200));
}
sub vcl_synth {
if (req.http.Called) {
set resp.http.Called = req.http.Called;
}
return (deliver);
}
}
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
...
...
@@ -229,6 +321,23 @@ logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect * = End
} -start
logexpect l2 -v v1 -d 0 -g vxid -q "Notice" {
expect 0 * Begin req
expect * = Notice {^vmod_selector: s\.check_call\(\) called without prior match$}
expect 0 = ReqHeader {^Check-Call: false$}
expect * = End
expect 0 * Begin req
expect * = Notice {^vmod_selector: s\.check_call\(\) called without prior match$}
expect 0 = ReqHeader {^Check-Call: false$}
expect * = End
expect 0 * Begin req
expect * = Notice {^vmod_selector: s\.check_call\(6\): set has 5 elements$}
expect 0 = ReqHeader {^Check-Call: false$}
expect * = End
} -start
client c1 {
txreq -hdr "Int: -1"
rxresp
...
...
@@ -257,6 +366,7 @@ client c1 {
} -run
logexpect l1 -wait
logexpect l2 -wait
varnish v1 -vcl {
import ${vmod_selector};
...
...
@@ -289,6 +399,17 @@ varnish v1 -vcl {
sub vcl_synth {
if (s.hasprefix(req.http.Word)) {
set resp.http.Check-Noarg = s.check_call();
set resp.http.Check-Unique
= s.check_call(select=UNIQUE);
set resp.http.Check-Exact = s.check_call(select=EXACT);
set resp.http.Check-First = s.check_call(select=FIRST);
set resp.http.Check-Last = s.check_call(select=LAST);
set resp.http.Check-Shortest
= s.check_call(select=SHORTEST);
set resp.http.Check-Longest
= s.check_call(select=LONGEST);
call s.subroutine();
call s.subroutine(select=UNIQUE);
call s.subroutine(select=EXACT);
...
...
@@ -299,6 +420,17 @@ varnish v1 -vcl {
}
if (req.http.Element) {
call s.subroutine(element=req.http.Element);
set resp.http.Check-Unique
= s.check_call(select=UNIQUE);
set resp.http.Check-Exact = s.check_call(select=EXACT);
set resp.http.Check-First = s.check_call(select=FIRST);
set resp.http.Check-Last = s.check_call(select=LAST);
set resp.http.Check-Shortest
= s.check_call(select=SHORTEST);
set resp.http.Check-Longest
= s.check_call(select=LONGEST);
call s.subroutine(select=UNIQUE);
call s.subroutine(select=EXACT);
call s.subroutine(select=FIRST);
...
...
@@ -315,12 +447,25 @@ client c1 {
rxresp
expect resp.status == 200
expect resp.http.Foo == "XXXXXXX"
expect resp.http.Check-Noarg == true
expect resp.http.Check-Unique == true
expect resp.http.Check-Exact == true
expect resp.http.Check-First == true
expect resp.http.Check-Last == true
expect resp.http.Check-Longest == true
expect resp.http.Check-Shortest == true
expect resp.http.Called == <undef>
txreq -hdr "Element: foo"
rxresp
expect resp.status == 200
expect resp.http.Foo == "XXXXXXX"
expect resp.http.Check-Unique == true
expect resp.http.Check-Exact == true
expect resp.http.Check-First == true
expect resp.http.Check-Last == true
expect resp.http.Check-Longest == true
expect resp.http.Check-Shortest == true
expect resp.http.Called == <undef>
} -run
...
...
@@ -380,6 +525,17 @@ varnish v1 -vcl {
sub vcl_synth {
if (s.hasprefix(req.http.Word)) {
set resp.http.Check-Noarg = s.check_call();
set resp.http.Check-Unique
= s.check_call(select=UNIQUE);
set resp.http.Check-Exact = s.check_call(select=EXACT);
set resp.http.Check-First = s.check_call(select=FIRST);
set resp.http.Check-Last = s.check_call(select=LAST);
set resp.http.Check-Shortest
= s.check_call(select=SHORTEST);
set resp.http.Check-Longest
= s.check_call(select=LONGEST);
set resp.http.X = "E";
call s.subroutine(select=EXACT);
set resp.http.X = "F";
...
...
@@ -395,10 +551,34 @@ varnish v1 -vcl {
}
}
logexpect l1 -v v1 -d 0 -g vxid -q "Notice" {
expect 0 * Begin req
expect * = Notice {^vmod_selector: s\.check_call\(select=UNIQUE\): 2 elements were matched$}
expect * = Notice {^vmod_selector: s\.check_call\(select=UNIQUE\): 2 elements were matched$}
expect * = End
expect 0 * Begin req
expect * = Notice {^vmod_selector: s\.check_call\(select=UNIQUE\): 3 elements were matched$}
expect * = Notice {^vmod_selector: s\.check_call\(select=UNIQUE\): 3 elements were matched$}
expect * = End
expect 0 * Begin req
expect * = Notice {^vmod_selector: s\.check_call\(select=UNIQUE\): 4 elements were matched$}
expect * = Notice {^vmod_selector: s\.check_call\(select=UNIQUE\): 4 elements were matched$}
expect * = End
} -start
client c1 {
txreq -hdr "Word: foobar"
rxresp
expect resp.status == 200
expect resp.http.Check-Noarg == false
expect resp.http.Check-Unique == false
expect resp.http.Check-Exact == true
expect resp.http.Check-First == true
expect resp.http.Check-Last == true
expect resp.http.Check-Longest == true
expect resp.http.Check-Shortest == true
expect resp.http.Foo == "LaS"
expect resp.http.Foobar == "EFLo"
expect resp.http.Foobarbaz == <undef>
...
...
@@ -407,6 +587,13 @@ client c1 {
txreq -hdr "Word: foobarbaz"
rxresp
expect resp.status == 200
expect resp.http.Check-Noarg == false
expect resp.http.Check-Unique == false
expect resp.http.Check-Exact == true
expect resp.http.Check-First == true
expect resp.http.Check-Last == true
expect resp.http.Check-Longest == true
expect resp.http.Check-Shortest == true
expect resp.http.Foo == "LaS"
expect resp.http.Foobar == <undef>
expect resp.http.Foobarbaz == "EFLo"
...
...
@@ -415,12 +602,21 @@ client c1 {
txreq -hdr "Word: foobarbazquux"
rxresp
expect resp.status == 200
expect resp.http.Check-Noarg == false
expect resp.http.Check-Unique == false
expect resp.http.Check-Exact == true
expect resp.http.Check-First == true
expect resp.http.Check-Last == true
expect resp.http.Check-Longest == true
expect resp.http.Check-Shortest == true
expect resp.http.Foo == "LaS"
expect resp.http.Foobar == <undef>
expect resp.http.Foobarbaz == <undef>
expect resp.http.Foobarbazquux == "EFLo"
} -run
logexpect l1 -wait
varnish v1 -vcl {
import ${vmod_selector};
backend b None;
...
...
@@ -451,6 +647,8 @@ varnish v1 -vcl {
sub vcl_recv {
if (s.hasprefix(req.http.Word)) {
set req.http.Check-Unique = s.check_call(select=UNIQUE);
set req.http.Check-Exact = s.check_call(select=EXACT);
call s.subroutine(select=EXACT);
call s.subroutine(select=UNIQUE);
}
...
...
@@ -471,6 +669,21 @@ logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect * = End
} -start
logexpect l2 -v v1 -d 0 -g vxid -q "Notice" {
expect 0 * Begin req
expect * = Notice {^vmod_selector: s\.check_call\(select=UNIQUE\): 2 elements were matched$}
expect 0 = ReqHeader {^Check-Unique: false$}
expect 0 = ReqHeader {^Check-Exact: true$}
expect * = End
expect 0 * Begin req
expect * = Notice {^vmod_selector: s\.check_call\(select=UNIQUE\): 2 elements were matched$}
expect 0 = ReqHeader {^Check-Unique: false$}
expect 0 = Notice {^vmod_selector: s\.check_call\(select=EXACT\): no element matched exactly$}
expect 0 = ReqHeader {^Check-Exact: false$}
expect * = End
} -start
client c1 {
txreq -hdr "Word: foobar"
rxresp
...
...
@@ -488,6 +701,7 @@ client c1 {
} -run
logexpect l1 -wait
logexpect l2 -wait
varnish v1 -vcl {
import ${vmod_selector};
...
...
@@ -505,12 +719,14 @@ varnish v1 -vcl {
sub vcl_recv {
if (s.match(req.http.Word)) {
set req.http.Check = s.check_call();
call s.subroutine();
}
return (synth(200));
}
sub vcl_synth {
set resp.http.Check = req.http.Check;
set resp.http.Foo = req.http.Foo;
return (deliver);
}
...
...
@@ -523,10 +739,18 @@ logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect * = End
} -start
logexpect l2 -v v1 -d 0 -g vxid -q "Notice" {
expect 0 * Begin req
expect * = Notice {^vmod_selector: s\.check_call\(\): subroutine not added for element 2$}
expect 0 = ReqHeader {^Check: false$}
expect * = End
} -start
client c1 {
txreq -hdr "Word: foo"
rxresp
expect resp.status == 200
expect resp.http.Check == "true"
expect resp.http.Foo == "called"
txreq -hdr "Word: bar"
...
...
@@ -537,6 +761,7 @@ client c1 {
} -run
logexpect l1 -wait
logexpect l2 -wait
varnish v1 -errvcl {Symbol not found: 'foo'} {
import ${vmod_selector};
...
...
@@ -562,6 +787,7 @@ varnish v1 -vcl {
}
sub vcl_recv {
set req.http.Check = s.check_call(element="foo");
call s.subroutine(element="foo");
return (synth(200));
}
...
...
@@ -574,6 +800,13 @@ logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect * = End
} -start
logexpect l2 -v v1 -d 0 -g vxid -q "Notice" {
expect 0 * Begin req
expect * = Notice {^vmod_selector: Dynamic call to "sub foo\{\}" not allowed from here$}
expect 0 = ReqHeader {^Check: false$}
expect * = End
} -start
client c1 {
txreq
rxresp
...
...
@@ -583,6 +816,7 @@ client c1 {
} -run
logexpect l1 -wait
logexpect l2 -wait
varnish v1 -vcl {
import ${vmod_selector};
...
...
@@ -598,6 +832,7 @@ varnish v1 -vcl {
}
sub bar {
set req.http.Check = s.check_call(element="foo");
call s.subroutine(element="foo");
}
...
...
@@ -614,6 +849,13 @@ logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect * = End
} -start
logexpect l2 -v v1 -d 0 -g vxid -q "Notice" {
expect 0 * Begin req
expect * = Notice {^vmod_selector: Recursive dynamic call to "sub foo\{\}"$}
expect 0 = ReqHeader {^Check: false$}
expect * = End