Commit b0bf452d by Geoff Simmons

Add the set.string() and backend() methods.

parent dc7d6432
Pipeline #335 skipped
......@@ -725,7 +725,7 @@ set.add
::
VOID set.add(STRING)
VOID set.add(STRING, STRING string=0, BACKEND backend=0)
Add the given pattern to the set. If the pattern is invalid,
``.add()`` fails, and the VCL will fail to load, with an error message
......@@ -885,6 +885,24 @@ Example::
+ " patterns from the set");
}
.. _func_set.string:
set.string
----------
::
STRING set.string(INT n=0)
.. _func_set.backend:
set.backend
-----------
::
BACKEND set.backend(INT n=0)
.. _func_version:
version
......
# looks like -*- vcl -*-
varnishtest "set .string() and .backend() methods"
varnish v1 -vcl {
import ${vmod_re2};
backend b1 { .host = "${bad_ip}"; }
backend b2 { .host = "${bad_ip}"; }
sub vcl_init {
new s = re2.set();
s.add("foo", "baz");
s.add("bar", "quux");
s.compile();
new b = re2.set();
b.add("foo", backend=b1);
b.add("bar", backend=b2);
b.compile();
}
sub vcl_recv {
return(synth(200));
}
sub vcl_synth {
set resp.http.s-str-1 = s.string(1);
set resp.http.s-str-2 = s.string(2);
set resp.http.s-before-match = s.string();
set resp.http.s-foo-match = s.match("foo");
set resp.http.s-foo-n = s.nmatches();
set resp.http.s-foo-str = s.string();
set resp.http.s-bar-match = s.match("bar");
set resp.http.s-bar-n = s.nmatches();
set resp.http.s-bar-str = s.string();
set resp.http.s-bar-str-0 = s.string(0);
set resp.http.s-bar-str-1 = s.string(-1);
set resp.http.s-fail-match = s.match("fail");
set resp.http.s-fail-n = s.nmatches();
set resp.http.s-fail-str = s.string();
set resp.http.s-toomany-match = s.match("foobar");
set resp.http.s-toomany-n = s.nmatches();
set resp.http.s-toomany-str = s.string();
set resp.http.b-backend-1 = b.backend(1);
set resp.http.b-backend-2 = b.backend(2);
set resp.http.b-before-match = b.backend();
set resp.http.b-foo-match = b.match("foo");
set resp.http.b-foo-n = b.nmatches();
set resp.http.b-foo-backend = b.backend();
set resp.http.b-bar-match = b.match("bar");
set resp.http.b-bar-n = b.nmatches();
set resp.http.b-bar-backend = b.backend();
set resp.http.b-bar-backend-0 = b.backend(0);
set resp.http.b-bar-backend-1 = b.backend(-1);
set resp.http.b-fail-match = b.match("fail");
set resp.http.b-fail-n = b.nmatches();
set resp.http.b-fail-backend = b.backend();
set resp.http.b-toomany-match = b.match("foobar");
set resp.http.b-toomany-n = b.nmatches();
set resp.http.b-toomany-backend = b.backend();
set resp.http.s-outofrange = s.string(3);
set resp.http.b-outofrange = b.backend(3);
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.s-str-1 == "baz"
expect resp.http.s-str-2 == "quux"
expect resp.http.s-before-match == ""
expect resp.http.s-foo-match == "true"
expect resp.http.s-foo-n == 1
expect resp.http.s-foo-str == "baz"
expect resp.http.s-bar-match == "true"
expect resp.http.s-bar-n == 1
expect resp.http.s-bar-str == "quux"
expect resp.http.s-bar-str-0 == resp.http.s-bar-str
expect resp.http.s-bar-str-1 == resp.http.s-bar-str
expect resp.http.s-fail-match == "false"
expect resp.http.s-fail-n == 0
expect resp.http.s-fail-str == ""
expect resp.http.s-toomany-match == "true"
expect resp.http.s-toomany-n == 2
expect resp.http.s-toomany-str == ""
expect resp.http.b-backend-1 == "b1"
expect resp.http.b-backend-2 == "b2"
expect resp.http.b-before-match == ""
expect resp.http.b-foo-match == "true"
expect resp.http.b-foo-n == 1
expect resp.http.b-foo-backend == "b1"
expect resp.http.b-bar-match == "true"
expect resp.http.b-bar-n == 1
expect resp.http.b-bar-backend == "b2"
expect resp.http.b-bar-backend-0 == resp.http.b-bar-backend
expect resp.http.b-bar-backend-1 == resp.http.b-bar-backend
expect resp.http.b-fail-match == "false"
expect resp.http.b-fail-n == 0
expect resp.http.b-fail-backend == ""
expect resp.http.b-toomany-match == "true"
expect resp.http.b-toomany-n == 2
expect resp.http.b-toomany-backend == ""
expect resp.http.s-outofrange == ""
expect resp.http.b-outofrange == ""
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error "^vmod re2 error: s.string.. called without prior match$"
expect * = VCL_Error "^vmod re2 error: s.string.0.: previous match was unsuccessful$"
expect * = VCL_Error "^vmod re2 error: s.string.0.: 2 successful matches$"
expect * = VCL_Error "^vmod re2 error: b.backend.. called without prior match$"
expect * = VCL_Error "^vmod re2 error: b.backend.0.: previous match was unsuccessful$"
expect * = VCL_Error "^vmod re2 error: b.backend.0.: 2 successful matches$"
expect * = VCL_Error "^vmod re2 error: s.string.3.: set has 2 patterns$"
expect * = VCL_Error "^vmod re2 error: b.backend.3.: set has 2 patterns$"
expect * = End
} -run
......@@ -67,6 +67,8 @@ struct vmod_re2_set {
#define VMOD_RE2_SET_MAGIC 0xf6d7b15a
vre2set *set;
char *vcl_name;
char **string;
VCL_BACKEND *backend;
unsigned compiled;
int npatterns;
};
......@@ -576,6 +578,8 @@ vmod_set__init(VRT_CTX, struct vmod_re2_set **setp, const char *vcl_name,
return;
}
set->vcl_name = strdup(vcl_name);
AZ(set->string);
AZ(set->backend);
AZ(set->npatterns);
}
......@@ -598,9 +602,11 @@ vmod_set__fini(struct vmod_re2_set **setp)
#define ERR_PREFIX "%s.add(\"%.40s\"): "
VCL_VOID
vmod_set_add(VRT_CTX, struct vmod_re2_set *set, VCL_STRING pattern)
vmod_set_add(VRT_CTX, struct vmod_re2_set *set, VCL_STRING pattern,
VCL_STRING string, VCL_BACKEND backend)
{
const char *err;
int n;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(set, VMOD_RE2_SET_MAGIC);
......@@ -622,6 +628,29 @@ vmod_set_add(VRT_CTX, struct vmod_re2_set *set, VCL_STRING pattern)
set->vcl_name, pattern, pattern, err);
return;
}
n = set->npatterns;
if (string != NULL) {
if ((set->string = realloc(set->string,
(n + 1) * (sizeof(char *))))
== NULL) {
VERRNOMEM(ctx, ERR_PREFIX "adding string %s",
set->vcl_name, pattern, string);
return;
}
REPLACE(set->string[n], string);
}
if (backend != NULL) {
if ((set->backend = realloc(set->backend,
(n + 1) * (sizeof(VCL_BACKEND))))
== NULL) {
VERRNOMEM(ctx, ERR_PREFIX "adding backend %s",
set->vcl_name, pattern,
VRT_BACKEND_string(backend));
return;
}
set->backend[n] = backend;
}
set->npatterns++;
}
......@@ -721,10 +750,24 @@ vmod_set_match(VRT_CTX, struct vmod_re2_set *set, VCL_STRING subject)
#undef ERR_PREFIX
static struct task_set_match *
get_task_data(VRT_CTX, struct vmod_re2_set *set)
{
struct vmod_priv *priv;
struct task_set_match *task;
priv = VRT_priv_task(ctx, set);
AN(priv);
if (priv->priv == NULL)
return NULL;
WS_Assert_Allocated(ctx->ws, priv->priv, sizeof(*task));
CAST_OBJ(task, priv->priv, TASK_SET_MATCH_MAGIC);
return task;
}
VCL_BOOL
vmod_set_matched(VRT_CTX, struct vmod_re2_set *set, VCL_INT n)
{
struct vmod_priv *priv;
struct task_set_match *task;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
......@@ -735,15 +778,11 @@ vmod_set_matched(VRT_CTX, struct vmod_re2_set *set, VCL_INT n)
return 0;
}
priv = VRT_priv_task(ctx, set);
AN(priv);
if (priv->priv == NULL) {
if ((task = get_task_data(ctx, set)) == NULL) {
VERR(ctx, "%s.matched(%d) called without prior match",
set->vcl_name, n);
return 0;
}
WS_Assert_Allocated(ctx->ws, priv->priv, sizeof(*task));
CAST_OBJ(task, priv->priv, TASK_SET_MATCH_MAGIC);
if (task->nmatches == 0)
return 0;
......@@ -759,23 +798,90 @@ vmod_set_matched(VRT_CTX, struct vmod_re2_set *set, VCL_INT n)
VCL_INT
vmod_set_nmatches(VRT_CTX, struct vmod_re2_set *set)
{
struct vmod_priv *priv;
struct task_set_match *task;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(set, VMOD_RE2_SET_MAGIC);
priv = VRT_priv_task(ctx, set);
AN(priv);
if (priv->priv == NULL) {
if ((task = get_task_data(ctx, set)) == NULL) {
VERR(ctx, "%s.nmatches() called without prior match",
set->vcl_name);
return 0;
}
WS_Assert_Allocated(ctx->ws, priv->priv, sizeof(*task));
CAST_OBJ(task, priv->priv, TASK_SET_MATCH_MAGIC);
return task->nmatches;
}
VCL_STRING
vmod_set_string(VRT_CTX, struct vmod_re2_set *set, VCL_INT n)
{
struct task_set_match *task;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(set, VMOD_RE2_SET_MAGIC);
if (n > set->npatterns) {
VERR(ctx, "%s.string(%lld): set has %d patterns", set->vcl_name,
n, set->npatterns);
return NULL;
}
if (n > 0)
return set->string[n - 1];
if ((task = get_task_data(ctx, set)) == NULL) {
VERR(ctx, "%s.string() called without prior match",
set->vcl_name);
return NULL;
}
if (task->nmatches == 0) {
VERR(ctx, "%s.string(%lld): previous match was unsuccessful",
set->vcl_name, n);
return NULL;
}
if (task->nmatches > 1) {
VERR(ctx, "%s.string(%lld): %d successful matches",
set->vcl_name, n, task->nmatches);
return NULL;
}
WS_Assert_Allocated(ctx->ws, task->matches,
task->nmatches * sizeof(int));
return set->string[task->matches[0]];
}
VCL_BACKEND
vmod_set_backend(VRT_CTX, struct vmod_re2_set *set, VCL_INT n)
{
struct task_set_match *task;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(set, VMOD_RE2_SET_MAGIC);
if (n > set->npatterns) {
VERR(ctx, "%s.backend(%lld): set has %d patterns",
set->vcl_name, n, set->npatterns);
return NULL;
}
if (n > 0)
return set->backend[n - 1];
if ((task = get_task_data(ctx, set)) == NULL) {
VERR(ctx, "%s.backend() called without prior match",
set->vcl_name);
return NULL;
}
if (task->nmatches == 0) {
VERR(ctx, "%s.backend(%lld): previous match was unsuccessful",
set->vcl_name, n);
return NULL;
}
if (task->nmatches > 1) {
VERR(ctx, "%s.backend(%lld): %d successful matches",
set->vcl_name, n, task->nmatches);
return NULL;
}
WS_Assert_Allocated(ctx->ws, task->matches,
task->nmatches * sizeof(int));
return set->backend[task->matches[0]];
}
/* Regex function interface */
#define ERR_PREFIX "re2.match(pattern=\"%.40s\", text=\"%.40s\"): "
......
......@@ -628,7 +628,7 @@ Example::
perl_classes=true);
}
$Method VOID .add(STRING)
$Method VOID .add(STRING, STRING string=0, BACKEND backend=0)
Add the given pattern to the set. If the pattern is invalid,
``.add()`` fails, and the VCL will fail to load, with an error message
......@@ -760,6 +760,10 @@ Example::
+ " patterns from the set");
}
$Method STRING .string(INT n=0)
$Method BACKEND .backend(INT n=0)
$Function STRING version()
Return the version string for this VMOD.
......
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