Commit 3a6150ca authored by Geoff Simmons's avatar Geoff Simmons

Add the integer param to .add(), and the .integer() method.

parent 5aa906a0
This diff is collapsed.
# looks like -*- vcl -*-
varnishtest "integer() method"
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new s = selector.set();
s.add("foo", integer=0);
s.add("bar", integer=1);
s.add("baz", integer=2);
s.add("quux", integer=-1);
s.add("foobar", integer=-2);
}
sub vcl_recv {
return (synth(200));
}
sub vcl_synth {
set resp.http.N-1 = s.integer(1);
set resp.http.N-2 = s.integer(2);
set resp.http.N-3 = s.integer(3);
set resp.http.N-4 = s.integer(4);
set resp.http.N-5 = s.integer(5);
if (s.match(req.http.Word)) {
set resp.http.Integer = s.integer();
set resp.http.Integer-Unique = s.integer(select=UNIQUE);
set resp.http.Integer-Exact = s.integer(select=EXACT);
set resp.http.Integer-First = s.integer(select=FIRST);
set resp.http.Integer-Last = s.integer(select=LAST);
set resp.http.Integer-Shortest
= s.integer(select=SHORTEST);
set resp.http.Integer-Longest
= s.integer(select=LONGEST);
}
return (deliver);
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.N-1 == 0
expect resp.http.N-2 == 1
expect resp.http.N-3 == 2
expect resp.http.N-4 == -1
expect resp.http.N-5 == -2
txreq -hdr "Word: foo"
rxresp
expect resp.status == 200
expect resp.http.Integer == 0
expect resp.http.Integer-Unique == resp.http.Integer
expect resp.http.Integer-Exact == resp.http.Integer
expect resp.http.Integer-First == 0
expect resp.http.Integer-Last == 0
expect resp.http.Integer-Shortest == 0
expect resp.http.Integer-Longest == 0
txreq -hdr "Word: bar"
rxresp
expect resp.status == 200
expect resp.http.Integer == 1
expect resp.http.Integer-Unique == resp.http.Integer
expect resp.http.Integer-Exact == resp.http.Integer
expect resp.http.Integer-First == 1
expect resp.http.Integer-Last == 1
expect resp.http.Integer-Shortest == 1
expect resp.http.Integer-Longest == 1
txreq -hdr "Word: baz"
rxresp
expect resp.status == 200
expect resp.http.Integer == 2
expect resp.http.Integer-Unique == resp.http.Integer
expect resp.http.Integer-Exact == resp.http.Integer
expect resp.http.Integer-First == 2
expect resp.http.Integer-Last == 2
expect resp.http.Integer-Shortest == 2
expect resp.http.Integer-Longest == 2
txreq -hdr "Word: quux"
rxresp
expect resp.status == 200
expect resp.http.Integer == -1
expect resp.http.Integer-Unique == resp.http.Integer
expect resp.http.Integer-Exact == resp.http.Integer
expect resp.http.Integer-First == -1
expect resp.http.Integer-Last == -1
expect resp.http.Integer-Shortest == -1
expect resp.http.Integer-Longest == -1
txreq -hdr "Word: foobar"
rxresp
expect resp.status == 200
expect resp.http.Integer == -2
expect resp.http.Integer-Unique == resp.http.Integer
expect resp.http.Integer-Exact == resp.http.Integer
expect resp.http.Integer-First == -2
expect resp.http.Integer-Last == -2
expect resp.http.Integer-Shortest == -2
expect resp.http.Integer-Longest == -2
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.match\(\): subject string is NULL$}
expect * = End
} -run
varnish v1 -vcl {
import ${vmod_selector};
import std;
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new s = selector.set();
s.add("foo", integer=0);
s.add("bar", integer=1);
s.add("baz", integer=2);
s.add("quux", integer=-1);
s.add("foobar", integer=-2);
}
sub vcl_recv {
set req.http.Integer = s.integer(std.integer(req.http.Int));
return (synth(200));
}
}
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.integer\(\) called without prior match$}
expect 0 = ReqHeader "Integer: 0"
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.integer\(\) called without prior match$}
expect 0 = ReqHeader "Integer: 0"
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.integer\(6\): set has 5 elements$}
expect 0 = ReqHeader "Integer: 0"
expect * = End
} -start
client c1 {
txreq -hdr "Int: -1"
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
expect_close
} -run
client c1 {
txreq -hdr "Int: 0"
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
expect_close
} -run
client c1 {
txreq -hdr "Int: 6"
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
expect_close
} -run
logexpect l1 -wait
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new s = selector.set();
s.add("foobarbazquux", integer=1);
s.add("foobarbaz", integer=2);
s.add("foobar", integer=3);
s.add("foo", integer=4);
}
sub vcl_recv {
return (synth(200));
}
sub vcl_synth {
if (s.hasprefix(req.http.Word)) {
set resp.http.Integer = s.integer();
set resp.http.Integer-Unique = s.integer(select=UNIQUE);
set resp.http.Integer-Exact = s.integer(select=EXACT);
set resp.http.Integer-First = s.integer(select=FIRST);
set resp.http.Integer-Last = s.integer(select=LAST);
set resp.http.Integer-Shortest
= s.integer(select=SHORTEST);
set resp.http.Integer-Longest
= s.integer(select=LONGEST);
}
return (deliver);
}
}
client c1 {
txreq -hdr "Word: foo"
rxresp
expect resp.status == 200
expect resp.http.Integer == 4
expect resp.http.Integer-Unique == 4
expect resp.http.Integer-Exact == 4
expect resp.http.Integer-First == 4
expect resp.http.Integer-Last == 4
expect resp.http.Integer-Shortest == 4
expect resp.http.Integer-Longest == 4
} -run
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new s = selector.set();
s.add("foobarbazquux", integer=1);
s.add("foobarbaz", integer=2);
s.add("foobar", integer=3);
s.add("foo", integer=4);
}
sub vcl_recv {
return (synth(200));
}
sub vcl_synth {
if (s.hasprefix(req.http.Word)) {
set resp.http.Integer-Exact = s.integer(select=EXACT);
set resp.http.Integer-First = s.integer(select=FIRST);
set resp.http.Integer-Last = s.integer(select=LAST);
set resp.http.Integer-Shortest
= s.integer(select=SHORTEST);
set resp.http.Integer-Longest
= s.integer(select=LONGEST);
}
return (deliver);
}
}
client c1 {
txreq -hdr "Word: foobar"
rxresp
expect resp.status == 200
expect resp.http.Integer-Exact == 3
expect resp.http.Integer-First == 3
expect resp.http.Integer-Last == 4
expect resp.http.Integer-Shortest == 4
expect resp.http.Integer-Longest == 3
txreq -hdr "Word: foobarbaz"
rxresp
expect resp.status == 200
expect resp.http.Integer-Exact == 2
expect resp.http.Integer-First == 2
expect resp.http.Integer-Last == 4
expect resp.http.Integer-Shortest == 4
expect resp.http.Integer-Longest == 2
txreq -hdr "Word: foobarbazquux"
rxresp
expect resp.status == 200
expect resp.http.Integer-Exact == 1
expect resp.http.Integer-First == 1
expect resp.http.Integer-Last == 4
expect resp.http.Integer-Shortest == 4
expect resp.http.Integer-Longest == 1
} -run
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new s = selector.set();
s.add("foobarbazquux", integer=1);
s.add("foobarbaz", integer=2);
s.add("foobar", integer=3);
s.add("foo", integer=4);
}
sub vcl_recv {
if (s.hasprefix(req.http.Word)) {
set req.http.Integer-Exact = s.integer(select=EXACT);
set req.http.Integer-Unique = s.integer(select=UNIQUE);
}
return (synth(200));
}
}
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect * * Begin req
expect * = ReqHeader "Integer-Exact: 3"
expect * = VCL_Error {^vmod selector error: s\.integer\(select=UNIQUE\): 2 elements were matched$}
expect 0 = ReqHeader "Integer-Unique: 0"
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.integer\(select=EXACT\): no element matched exactly$}
expect 0 = ReqHeader "Integer-Exact: 0"
expect * = End
} -start
client c1 {
txreq -hdr "Word: foobar"
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
expect_close
} -run
client c1 {
txreq -hdr "Word: foobarb"
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
expect_close
} -run
logexpect l1 -wait
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new s = selector.set();
s.add("foo", integer=0);
s.add("bar");
}
sub vcl_recv {
if (s.match(req.http.Word)) {
set req.http.Integer = s.integer();
}
return (synth(200));
}
sub vcl_synth {
set resp.http.Integer = req.http.Integer;
return (deliver);
}
}
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.integer\(\): integer not added for element 2$}
expect 0 = ReqHeader "Integer: 0"
expect * = End
} -start
client c1 {
txreq -hdr "Word: foo"
rxresp
expect resp.status == 200
expect resp.http.Integer == 0
txreq -hdr "Word: bar"
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
expect_close
} -run
logexpect l1 -wait
......@@ -61,12 +61,14 @@ struct entry {
char *string;
VCL_BACKEND backend;
vre_t *re;
VCL_INT integer;
};
enum bitmap_e {
STRING = 0,
BACKEND,
REGEX,
INTEGER,
__MAX_BITMAP,
};
......@@ -240,8 +242,8 @@ vmod_set__fini(struct vmod_selector_set **setp)
}
VCL_VOID
vmod_set_add(VRT_CTX, struct vmod_selector_set *set, VCL_STRING member,
VCL_STRING string, VCL_STRING regex, VCL_BACKEND backend)
vmod_set_add(VRT_CTX, struct vmod_selector_set *set,
struct VARGS(set_add) *args)
{
struct entry *entry;
unsigned n;
......@@ -252,7 +254,8 @@ vmod_set_add(VRT_CTX, struct vmod_selector_set *set, VCL_STRING member,
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(set, VMOD_SELECTOR_SET_MAGIC);
CHECK_OBJ_ORNULL(backend, DIRECTOR_MAGIC);
AN(args);
CHECK_OBJ_ORNULL(args->backend, DIRECTOR_MAGIC);
if ((ctx->method & VCL_MET_INIT) == 0) {
VFAIL(ctx, "%s.add() may only be called in vcl_init",
......@@ -260,7 +263,7 @@ vmod_set_add(VRT_CTX, struct vmod_selector_set *set, VCL_STRING member,
return;
}
if (member == NULL) {
if (args->arg1 == NULL) {
VFAIL(ctx, "%s.add(): string to be added is NULL",
set->vcl_name);
return;
......@@ -270,7 +273,7 @@ vmod_set_add(VRT_CTX, struct vmod_selector_set *set, VCL_STRING member,
n = set->nmembers;
set->members = realloc(set->members, n * sizeof(VCL_STRING));
AN(set->members);
set->members[n - 1] = strdup(member);
set->members[n - 1] = strdup(args->arg1);
AN(set->members[n - 1]);
members = set->members;
......@@ -278,7 +281,7 @@ vmod_set_add(VRT_CTX, struct vmod_selector_set *set, VCL_STRING member,
set->lomembers = realloc(set->lomembers,
n * sizeof(VCL_STRING));
AN(set->lomembers);
set->lomembers[n - 1] = strdup(member);
set->lomembers[n - 1] = strdup(args->arg1);
AN(set->lomembers[n - 1]);
for (char *m = set->lomembers[n-1]; *m; m++)
*m = tolower(*m);
......@@ -289,43 +292,49 @@ vmod_set_add(VRT_CTX, struct vmod_selector_set *set, VCL_STRING member,
if (PT_Insert(&set->origo, n - 1, members) != 0) {
if (errno == EINVAL)
VFAIL(ctx, "%s.add(): \"%s\" added more than once",
set->vcl_name, member);
set->vcl_name, args->arg1);
else
VFAIL(ctx, "%s.add(\"%s\") failed: %s", set->vcl_name,
member, strerror(errno));
args->arg1, strerror(errno));
return;
}
if (regex != NULL) {
if (args->valid_regex) {
/* XXX expose VRE options */
re = VRE_compile(regex, 0, &error, &erroffset);
re = VRE_compile(args->regex, 0, &error, &erroffset);
if (re == NULL) {
VFAIL(ctx, "%s.add(): cannot compile regular expression"
" '%s': %s at offset %d", set->vcl_name, regex,
error, erroffset);
" '%s': %s at offset %d", set->vcl_name,
args->regex, error, erroffset);
return;
}
}
if (string == NULL && re == NULL && backend == NULL)
if (!args->valid_string && re == NULL && !args->valid_backend
&& !args->valid_integer)
return;
set->table = realloc(set->table, n * sizeof(struct entry *));
AN(set->table);
ALLOC_OBJ(entry, VMOD_SELECTOR_ENTRY_MAGIC);
AN(entry);
if (string != NULL) {
entry->string = strdup(string);
if (args->valid_string) {
AN(args->string);
entry->string = strdup(args->string);
set_added(set, n - 1, STRING);
}
if (re != NULL) {
entry->re = re;
set_added(set, n - 1, REGEX);
}
if (backend != NULL) {
entry->backend = backend;
if (args->valid_backend) {
entry->backend = args->backend;
set_added(set, n - 1, BACKEND);
}
if (args->valid_integer) {
entry->integer = args->integer;
set_added(set, n - 1, INTEGER);
}
set->table[n - 1] = entry;
}
......@@ -676,6 +685,28 @@ vmod_set_string(VRT_CTX, struct vmod_selector_set * set, VCL_INT n,
return (s);
}
VCL_INT
vmod_set_integer(VRT_CTX, struct vmod_selector_set * set, VCL_INT n,
VCL_ENUM selects)
{
unsigned idx;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(set, VMOD_SELECTOR_SET_MAGIC);
idx = get_idx(ctx, n, set, "integer", selects);
if (idx == UINT_MAX) {
*ctx->handling = VCL_RET_FAIL;
return (0);
}
if (!check_added(ctx, set, idx, INTEGER, "integer", "integer")) {
*ctx->handling = VCL_RET_FAIL;
return (0);
}
return (set->table[idx]->integer);
}
static vre_t *
get_re(VRT_CTX, const struct vmod_selector_set * const restrict set,
VCL_INT n, VCL_ENUM const restrict selects,
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment