Commit 02ce5905 authored by Geoff Simmons's avatar Geoff Simmons

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

parent 88dea3a7
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, -7));
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 { ...@@ -61,12 +61,14 @@ struct entry {
char *string; char *string;
VCL_BACKEND backend; VCL_BACKEND backend;
vre_t *re; vre_t *re;
VCL_INT integer;
}; };
enum bitmap_e { enum bitmap_e {
STRING = 0, STRING = 0,
BACKEND, BACKEND,
REGEX, REGEX,
INTEGER,
__MAX_BITMAP, __MAX_BITMAP,
}; };
...@@ -240,8 +242,8 @@ vmod_set__fini(struct vmod_selector_set **setp) ...@@ -240,8 +242,8 @@ vmod_set__fini(struct vmod_selector_set **setp)
} }
VCL_VOID VCL_VOID
vmod_set_add(VRT_CTX, struct vmod_selector_set *set, VCL_STRING member, vmod_set_add(VRT_CTX, struct vmod_selector_set *set,
VCL_STRING string, VCL_STRING regex, VCL_BACKEND backend) struct vmod_set_add_arg *args)
{ {
struct entry *entry; struct entry *entry;
unsigned n; unsigned n;
...@@ -252,7 +254,8 @@ vmod_set_add(VRT_CTX, struct vmod_selector_set *set, VCL_STRING member, ...@@ -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(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(set, VMOD_SELECTOR_SET_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) { if ((ctx->method & VCL_MET_INIT) == 0) {
VFAIL(ctx, "%s.add() may only be called in vcl_init", 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, ...@@ -260,7 +263,7 @@ vmod_set_add(VRT_CTX, struct vmod_selector_set *set, VCL_STRING member,
return; return;
} }
if (member == NULL) { if (args->arg1 == NULL) {
VFAIL(ctx, "%s.add(): string to be added is NULL", VFAIL(ctx, "%s.add(): string to be added is NULL",
set->vcl_name); set->vcl_name);
return; return;
...@@ -270,7 +273,7 @@ vmod_set_add(VRT_CTX, struct vmod_selector_set *set, VCL_STRING member, ...@@ -270,7 +273,7 @@ vmod_set_add(VRT_CTX, struct vmod_selector_set *set, VCL_STRING member,
n = set->nmembers; n = set->nmembers;
set->members = realloc(set->members, n * sizeof(VCL_STRING)); set->members = realloc(set->members, n * sizeof(VCL_STRING));
AN(set->members); AN(set->members);
set->members[n - 1] = strdup(member); set->members[n - 1] = strdup(args->arg1);
AN(set->members[n - 1]); AN(set->members[n - 1]);
members = set->members; members = set->members;
...@@ -278,7 +281,7 @@ vmod_set_add(VRT_CTX, struct vmod_selector_set *set, VCL_STRING member, ...@@ -278,7 +281,7 @@ vmod_set_add(VRT_CTX, struct vmod_selector_set *set, VCL_STRING member,
set->lomembers = realloc(set->lomembers, set->lomembers = realloc(set->lomembers,
n * sizeof(VCL_STRING)); n * sizeof(VCL_STRING));
AN(set->lomembers); AN(set->lomembers);
set->lomembers[n - 1] = strdup(member); set->lomembers[n - 1] = strdup(args->arg1);
AN(set->lomembers[n - 1]); AN(set->lomembers[n - 1]);
for (char *m = set->lomembers[n-1]; *m; m++) for (char *m = set->lomembers[n-1]; *m; m++)
*m = tolower(*m); *m = tolower(*m);
...@@ -289,43 +292,49 @@ vmod_set_add(VRT_CTX, struct vmod_selector_set *set, VCL_STRING member, ...@@ -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 (PT_Insert(&set->origo, n - 1, members) != 0) {
if (errno == EINVAL) if (errno == EINVAL)
VFAIL(ctx, "%s.add(): \"%s\" added more than once", VFAIL(ctx, "%s.add(): \"%s\" added more than once",
set->vcl_name, member); set->vcl_name, args->arg1);
else else
VFAIL(ctx, "%s.add(\"%s\") failed: %s", set->vcl_name, VFAIL(ctx, "%s.add(\"%s\") failed: %s", set->vcl_name,
member, strerror(errno)); args->arg1, strerror(errno));
return; return;
} }
if (regex != NULL) { if (args->valid_regex) {
/* XXX expose VRE options */ /* XXX expose VRE options */
re = VRE_compile(regex, 0, &error, &erroffset); re = VRE_compile(args->regex, 0, &error, &erroffset);
if (re == NULL) { if (re == NULL) {
VFAIL(ctx, "%s.add(): cannot compile regular expression" VFAIL(ctx, "%s.add(): cannot compile regular expression"
" '%s': %s at offset %d", set->vcl_name, regex, " '%s': %s at offset %d", set->vcl_name,
error, erroffset); args->regex, error, erroffset);
return; return;
} }
} }
if (string == NULL && re == NULL && backend == NULL) if (!args->valid_string && re == NULL && !args->valid_backend
&& !args->valid_integer)
return; return;
set->table = realloc(set->table, n * sizeof(struct entry *)); set->table = realloc(set->table, n * sizeof(struct entry *));
AN(set->table); AN(set->table);
ALLOC_OBJ(entry, VMOD_SELECTOR_ENTRY_MAGIC); ALLOC_OBJ(entry, VMOD_SELECTOR_ENTRY_MAGIC);
AN(entry); AN(entry);
if (string != NULL) { if (args->valid_string) {
entry->string = strdup(string); AN(args->string);
entry->string = strdup(args->string);
set_added(set, n - 1, STRING); set_added(set, n - 1, STRING);
} }
if (re != NULL) { if (re != NULL) {
entry->re = re; entry->re = re;
set_added(set, n - 1, REGEX); set_added(set, n - 1, REGEX);
} }
if (backend != NULL) { if (args->valid_backend) {
entry->backend = backend; entry->backend = args->backend;
set_added(set, n - 1, 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; set->table[n - 1] = entry;
} }
...@@ -676,6 +685,28 @@ vmod_set_string(VRT_CTX, struct vmod_selector_set * set, VCL_INT n, ...@@ -676,6 +685,28 @@ vmod_set_string(VRT_CTX, struct vmod_selector_set * set, VCL_INT n,
return (s); 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 * static vre_t *
get_re(VRT_CTX, const struct vmod_selector_set * const restrict set, get_re(VRT_CTX, const struct vmod_selector_set * const restrict set,
VCL_INT n, VCL_ENUM const restrict selects, 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