Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
libvmod-re2
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-re2
Commits
04b3e9e0
Commit
04b3e9e0
authored
Apr 22, 2021
by
Geoff Simmons
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add the .check_call() method.
parent
7edfb217
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
385 additions
and
0 deletions
+385
-0
README.md
README.md
+9
-0
set.c
src/set.c
+75
-0
subroutine.vtc
src/tests/subroutine.vtc
+294
-0
vmod_re2.h
src/vmod_re2.h
+3
-0
vmod_re2.vcc
src/vmod_re2.vcc
+4
-0
No files found.
README.md
View file @
04b3e9e0
...
...
@@ -1533,6 +1533,15 @@ Example:
XXX ...
#### BOOL xset.check\_call(INT n, ENUM select)
BOOL xset.check_call(
INT n=0,
ENUM {FIRST, LAST, UNIQUE} select=UNIQUE
)
XXX ...
#### BOOL xset.saved(ENUM which, INT n, ENUM select)
BOOL xset.saved(
...
...
src/set.c
View file @
04b3e9e0
...
...
@@ -782,6 +782,81 @@ vmod_set_subroutine(VRT_CTX, struct VPFX(re2_set) *set, VCL_INT n,
return
set
->
sub
[
idx
];
}
VCL_BOOL
vmod_set_check_call
(
VRT_CTX
,
struct
VPFX
(
re2_set
)
*
set
,
VCL_INT
n
,
VCL_ENUM
selects
)
{
struct
task_set_match
*
task
;
int
idx
=
0
;
VCL_STRING
err
;
CHECK_OBJ_NOTNULL
(
ctx
,
VRT_CTX_MAGIC
);
CHECK_OBJ_NOTNULL
(
set
,
VMOD_RE2_SET_MAGIC
);
if
(
set
->
sub
==
NULL
)
{
VNOTICE
(
ctx
,
"%s.check_call(%jd): No subroutines were set for %s"
,
set
->
vcl_name
,
(
intmax_t
)
n
,
set
->
vcl_name
);
return
(
0
);
}
/*
* XXX: considerable DRY with get_match_idx().
* get_match_idx() invokes VRT_fail(), but we need to log
* SLT_Notice here, and the two alternatives are hard to
* disentangle within get_match_idx(). An alternative would be to
* pass in a flag to get_match_idx() that chooses between the two,
* and then we have to add the flag everywhere else. Consider
* that if we add anything else that needs SLT_Notice.
*/
if
(
n
>
set
->
npatterns
)
{
VNOTICE
(
ctx
,
"%s.check_call(%jd): set has %d patterns"
,
set
->
vcl_name
,
(
intmax_t
)
n
,
set
->
npatterns
);
return
(
0
);
}
if
(
n
<=
0
)
{
if
((
task
=
get_task_data
(
ctx
,
set
))
==
NULL
)
{
VNOTICE
(
ctx
,
"%s.check_call() called without prior match"
,
set
->
vcl_name
);
return
(
0
);
}
if
(
task
->
nmatches
==
0
)
{
VNOTICE
(
ctx
,
"%s.check_call(%jd): previous match was "
"unsuccessful"
,
set
->
vcl_name
,
(
intmax_t
)
n
);
return
(
0
);
}
if
(
task
->
nmatches
>
1
)
{
if
(
selects
==
VENUM
(
UNIQUE
))
{
VNOTICE
(
ctx
,
"%s.check_call(%jd): %ld "
"successful matches"
,
set
->
vcl_name
,
(
intmax_t
)
n
,
task
->
nmatches
);
return
(
0
);
}
if
(
selects
==
VENUM
(
LAST
))
idx
=
task
->
nmatches
-
1
;
else
assert
(
selects
==
VENUM
(
FIRST
));
}
WS_Assert_Allocated
(
ctx
->
ws
,
task
->
matches
,
task
->
nmatches
*
sizeof
(
int
));
idx
=
task
->
matches
[
idx
];
}
if
(
!
vbit_test
(
set
->
added
[
SUBROUTINE
],
idx
))
{
AN
(
selects
);
VNOTICE
(
ctx
,
"%s.check_call(%jd, %s): subroutine %d was not added"
,
set
->
vcl_name
,
n
,
selects
,
idx
+
1
);
return
(
0
);
}
if
((
err
=
VRT_check_call
(
ctx
,
set
->
sub
[
idx
]))
!=
NULL
)
{
VNOTICE
(
ctx
,
"%s.check_call(): %s"
,
set
->
vcl_name
,
err
);
return
(
0
);
}
return
(
1
);
}
VCL_BOOL
vmod_set_saved
(
VRT_CTX
,
struct
vmod_re2_set
*
set
,
VCL_ENUM
whichs
,
VCL_INT
n
,
VCL_ENUM
selects
)
...
...
src/tests/subroutine.vtc
View file @
04b3e9e0
...
...
@@ -35,12 +35,22 @@ varnish v1 -vcl+backend {
}
sub vcl_deliver {
set resp.http.Check-1 = s.check_call(1);
set resp.http.Check-2 = s.check_call(2);
set resp.http.X = "N";
call s.subroutine(1);
call s.subroutine(2);
set resp.http.s-saved-1 = s.saved(SUB, 1);
set resp.http.s-saved-2 = s.saved(SUB, 2);
set resp.http.s-check-before-match = s.check_call();
set resp.http.s-check-unique-before-match =
s.check_call(select=UNIQUE);
set resp.http.s-check-first-before-match =
s.check_call(select=FIRST);
set resp.http.s-check-last-before-match =
s.check_call(select=LAST);
if (req.http.Test == "b4match") {
if (req.http.Call == "subroutine") {
call s.subroutine();
...
...
@@ -53,12 +63,20 @@ varnish v1 -vcl+backend {
set resp.http.s-foo-match = s.match("foo");
set resp.http.s-foo-n = s.nmatches();
set resp.http.Foo-Check = s.check_call();
set resp.http.Foo-Check-Unique = s.check_call(select=UNIQUE);
set resp.http.Foo-Check-First = s.check_call(select=FIRST);
set resp.http.Foo-Check-Last = s.check_call(select=LAST);
set resp.http.X = "F";
call s.subroutine();
set resp.http.s-foo-saved = s.saved(SUB);
set resp.http.s-bar-match = s.match("bar");
set resp.http.s-bar-n = s.nmatches();
set resp.http.Bar-Check = s.check_call();
set resp.http.Bar-Check-Unique = s.check_call(select=UNIQUE);
set resp.http.Bar-Check-First = s.check_call(select=FIRST);
set resp.http.Bar-Check-Last = s.check_call(select=LAST);
set resp.http.X = "B";
call s.subroutine();
set resp.http.s-bar-saved = s.saved(SUB);
...
...
@@ -66,9 +84,15 @@ varnish v1 -vcl+backend {
call s.subroutine(-1);
set resp.http.s-bar-saved-0 = s.saved(SUB, 0);
set resp.http.s-bar-saved-1 = s.saved(SUB, -1);
set resp.http.Bar-Check-0 = s.check_call(0);
set resp.http.Bar-Check-1 = s.check_call(-1);
set resp.http.s-fail-match = s.match("fail");
set resp.http.s-fail-n = s.nmatches();
set resp.http.Fail-Check = s.check_call();
set resp.http.Fail-Check-Unique = s.check_call(select=UNIQUE);
set resp.http.Fail-Check-First = s.check_call(select=FIRST);
set resp.http.Fail-Check-Last = s.check_call(select=LAST);
if (req.http.Test == "failmatch") {
set resp.http.X = "X";
if (req.http.Call == "subroutine") {
...
...
@@ -82,6 +106,10 @@ varnish v1 -vcl+backend {
set resp.http.s-many-match = s.match("foobar");
set resp.http.s-many-n = s.nmatches();
set resp.http.X = "2";
set resp.http.Many-Check = s.check_call();
set resp.http.Many-Check-Unique = s.check_call(select=UNIQUE);
set resp.http.Many-Check-First = s.check_call(select=FIRST);
set resp.http.Many-Check-Last = s.check_call(select=LAST);
call s.subroutine(select=FIRST);
call s.subroutine(select=LAST);
set resp.http.s-many-saved-first = s.saved(SUB, select=FIRST);
...
...
@@ -95,6 +123,7 @@ varnish v1 -vcl+backend {
set resp.http.s-many-saved = s.saved(SUB);
}
}
set resp.http.Range-Check = s.check_call(3);
if (req.http.Test == "range") {
set resp.http.X = "3";
call s.subroutine(3);
...
...
@@ -109,22 +138,74 @@ client c1 {
expect resp.status == 200
expect resp.http.Foo == "NF2"
expect resp.http.Bar == "NBBB2"
expect resp.http.Check-1 == "true"
expect resp.http.Check-2 == "true"
expect resp.http.s-saved-1 == "true"
expect resp.http.s-saved-2 == "true"
expect resp.http.s-check-before-match == "false"
expect resp.http.s-check-unique-before-match == "false"
expect resp.http.s-check-first-before-match == "false"
expect resp.http.s-check-last-before-match == "false"
expect resp.http.s-foo-match == "true"
expect resp.http.s-foo-n == 1
expect resp.http.Foo-Check == "true"
expect resp.http.Foo-Check-Unique == "true"
expect resp.http.Foo-Check-First == "true"
expect resp.http.Foo-Check-Last == "true"
expect resp.http.s-foo-saved == "true"
expect resp.http.s-bar-match == "true"
expect resp.http.s-bar-n == 1
expect resp.http.Bar-Check == "true"
expect resp.http.Bar-Check-Unique == "true"
expect resp.http.Bar-Check-First == "true"
expect resp.http.Bar-Check-Last == "true"
expect resp.http.s-bar-saved == "true"
expect resp.http.s-bar-saved-0 == "true"
expect resp.http.s-bar-saved-1 == "true"
expect resp.http.Bar-Check-0 == "true"
expect resp.http.Bar-Check-1 == "true"
expect resp.http.s-fail-match == "false"
expect resp.http.s-fail-n == 0
expect resp.http.Fail-Check == "false"
expect resp.http.Fail-Check-Unique == "false"
expect resp.http.Fail-Check-First == "false"
expect resp.http.Fail-Check-Last == "false"
expect resp.http.s-many-match == "true"
expect resp.http.s-many-n == 2
expect resp.http.Many-Check == "false"
expect resp.http.Many-Check-Unique == "false"
expect resp.http.Many-Check-First == "true"
expect resp.http.Many-Check-Last == "true"
expect resp.http.s-many-saved-first == "true"
expect resp.http.s-many-saved-last == "true"
expect resp.http.Range-Check == "false"
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "Notice" {
expect 0 * Begin req
expect * = Notice {^vmod_re2: s\.check_call\(\) called without prior match$}
expect 0 = RespHeader {^s-check-before-match: false$}
expect * = Notice {^vmod_re2: s\.check_call\(\) called without prior match$}
expect 0 = RespHeader {^s-check-unique-before-match: false$}
expect * = Notice {^vmod_re2: s\.check_call\(\) called without prior match$}
expect 0 = RespHeader {^s-check-first-before-match: false$}
expect * = Notice {^vmod_re2: s\.check_call\(\) called without prior match$}
expect 0 = RespHeader {^s-check-last-before-match: false$}
expect * = Notice {^vmod_re2: s\.check_call\(0\): previous match was unsuccessful$}
expect 0 = RespHeader {^Fail-Check: false$}
expect * = Notice {^vmod_re2: s\.check_call\(0\): previous match was unsuccessful$}
expect 0 = RespHeader {^Fail-Check-Unique: false$}
expect * = Notice {^vmod_re2: s\.check_call\(0\): previous match was unsuccessful$}
expect 0 = RespHeader {^Fail-Check-First: false$}
expect * = Notice {^vmod_re2: s\.check_call\(0\): previous match was unsuccessful$}
expect 0 = RespHeader {^Fail-Check-Last: false$}
expect * = Notice {^vmod_re2: s\.check_call\(0\): 2 successful matches$}
expect 0 = RespHeader {^Many-Check: false$}
expect * = Notice {^vmod_re2: s\.check_call\(0\): 2 successful matches$}
expect 0 = RespHeader {^Many-Check-Unique: false$}
expect * = Notice {^vmod_re2: s\.check_call\(3\): set has 2 patterns$}
expect 0 = RespHeader {^Range-Check: false$}
expect * = End
} -run
client c1 {
...
...
@@ -246,3 +327,216 @@ logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 = VCL_return fail
expect * = End
} -run
varnish v1 -vcl {
import ${vmod_re2};
backend b None;
sub foo {
set req.http.Foo = "called";
}
sub vcl_init {
new s = re2.set();
s.add("foo", sub=foo);
s.add("bar");
}
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);
}
}
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^s\.subroutine\(0, UNIQUE\): subroutine 2 was not added$}
expect * = VCL_return fail
expect * = End
} -start
logexpect l2 -v v1 -d 0 -g vxid -q "Notice" {
expect 0 * Begin req
expect * = Notice {^vmod_re2: s\.check_call\(0, UNIQUE\): subroutine 2 was not added$}
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"
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
expect resp.http.Check == ""
expect resp.http.Foo == ""
expect_close
} -run
logexpect l1 -wait
logexpect l2 -wait
varnish v1 -vcl {
import ${vmod_re2};
backend b None;
sub vcl_init {
new s = re2.set();
s.add("foo");
}
sub vcl_recv {
set req.http.Check = s.check_call(1);
call s.subroutine(1);
return (synth(200));
}
sub vcl_synth {
set resp.http.Check = req.http.Check;
return (deliver);
}
}
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^s\.subroutine\(1\): No subroutines were set for s$}
expect * = VCL_return fail
expect * = End
} -start
logexpect l2 -v v1 -d 0 -g vxid -q "Notice" {
expect 0 * Begin req
expect * = Notice {^vmod_re2: s\.check_call\(1\): No subroutines were set for s$}
expect 0 = ReqHeader {^Check: false$}
expect * = End
} -start
client c1 {
txreq
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
expect resp.http.Check == ""
expect_close
} -run
logexpect l1 -wait
logexpect l2 -wait
varnish v1 -errvcl {Symbol not found: 'foo'} {
import ${vmod_re2};
backend b None;
sub vcl_init {
new s = re2.set();
s.add("foo", sub=foo);
}
}
varnish v1 -vcl {
import ${vmod_re2};
backend b None;
sub foo {
set bereq.http.Foo = "called";
}
sub vcl_init {
new s = re2.set();
s.add("foo", sub=foo);
}
sub vcl_recv {
set req.http.Check = s.check_call(1);
call s.subroutine(1);
return (synth(200));
}
}
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^call to "sub foo\{\}" not allowed from here$}
expect * = VCL_return fail
expect * = End
} -start
logexpect l2 -v v1 -d 0 -g vxid -q "Notice" {
expect 0 * Begin req
expect * = Notice {^vmod_re2: s\.check_call\(\): Dynamic call to "sub foo\{\}" not allowed from here$}
expect 0 = ReqHeader {^Check: false$}
expect * = End
} -start
client c1 {
txreq
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
expect_close
} -run
logexpect l1 -wait
logexpect l2 -wait
varnish v1 -vcl {
import ${vmod_re2};
backend b None;
sub foo {
call bar;
}
sub vcl_init {
new s = re2.set();
s.add("foo", sub=foo);
}
sub bar {
set req.http.Check = s.check_call(1);
call s.subroutine(1);
}
sub vcl_recv {
call foo;
return (synth(200));
}
}
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^Recursive call to "sub foo\{\}"$}
expect * = VCL_return fail
expect * = End
} -start
logexpect l2 -v v1 -d 0 -g vxid -q "Notice" {
expect 0 * Begin req
expect * = Notice {^vmod_re2: s\.check_call\(\): Recursive dynamic call to "sub foo\{\}"$}
expect 0 = ReqHeader {^Check: false$}
expect * = End
} -start
client c1 {
txreq
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
expect_close
} -run
logexpect l1 -wait
logexpect l2 -wait
src/vmod_re2.h
View file @
04b3e9e0
...
...
@@ -47,6 +47,9 @@
#define VERRNOMEM(ctx, fmt, ...) \
VFAIL((ctx), fmt ", out of space", __VA_ARGS__)
#define VNOTICE(ctx, fmt, ...) \
VSLb((ctx)->vsl, SLT_Notice, "vmod_re2: " fmt, __VA_ARGS__)
struct
vmod_re2_regex
{
unsigned
magic
;
#define VMOD_RE2_REGEX_MAGIC 0x5c3f6f24
...
...
src/vmod_re2.vcc
View file @
04b3e9e0
...
...
@@ -1401,6 +1401,10 @@ $Method SUB .subroutine(INT n=0, ENUM {FIRST, LAST, UNIQUE} select=UNIQUE)
XXX ...
$Method BOOL .check_call(INT n=0, ENUM {FIRST, LAST, UNIQUE} select=UNIQUE)
XXX ...
$Method BOOL .saved(ENUM {REGEX, STR, BE, INT, SUB} which=REGEX, INT n=0,
ENUM {FIRST, LAST, UNIQUE} select=UNIQUE)
...
...
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