Commit ad22becd authored by Geoff Simmons's avatar Geoff Simmons

Add the element parameter to .which().

parent 8d41e185
...@@ -39,9 +39,9 @@ SYNOPSIS ...@@ -39,9 +39,9 @@ SYNOPSIS
# Match properties # Match properties
INT <obj>.nmatches() INT <obj>.nmatches()
BOOL <obj>.matched([INT n] [, STRING element] [, ENUM select]) BOOL <obj>.matched([INT n] [, STRING element] [, ENUM select])
INT <obj>.which([ENUM select]) INT <obj>.which([ENUM select] [, STRING element])
# Retrieving objects after match # Retrieving objects by index, by string, or after match
STRING <obj>.element([INT n] [, ENUM select]) STRING <obj>.element([INT n] [, ENUM select])
STRING <obj>.string([INT n] [, STRING element] [, ENUM select]) STRING <obj>.string([INT n] [, STRING element] [, ENUM select])
INT <obj>.integer([INT n] [, STRING element] [, ENUM select]) INT <obj>.integer([INT n] [, STRING element] [, ENUM select])
...@@ -714,32 +714,37 @@ Example:: ...@@ -714,32 +714,37 @@ Example::
.. _xset.which(): .. _xset.which():
INT xset.which(ENUM select) INT xset.which(ENUM select, STRING element)
--------------------------- -------------------------------------------
:: ::
INT xset.which( INT xset.which(
ENUM {UNIQUE, EXACT, FIRST, LAST, SHORTEST, LONGEST} select=UNIQUE ENUM {UNIQUE, EXACT, FIRST, LAST, SHORTEST, LONGEST} select=UNIQUE,
STRING element=0
) )
After a successful ``.match()`` or ``.hasprefix()`` call for the same Return the index of the element indicated by ``element`` or
set object in the same task scope, return the index of the matching ``select``. The numbering corresponds to the order of ``.add()`` calls
element indicated by ``select``. The numbering corresponds to the in ``vcl_init``, starting from 1.
order of ``.add()`` calls in ``vcl_init``.
Return 0 if the most recent ``.match()`` or ``.hasprefix()`` call If the ``element`` parameter is set, then return the numeric index for
returned ``false``. that string in the set.
If more than one element matched after calling ``.hasprefix()``, the If ``element`` is unset, then the index is chosen with the ``select``
index is chosen with the ``select`` parameter, according to the rules parameter, and refers to the previous ``.match()`` or ``.hasprefix()``
given above. By default, ``select`` is ``UNIQUE``. call for the same set object in the same task scope, according to the
rules given above. By default, ``select`` is ``UNIQUE``.
If ``element`` is unset, and the most recent ``.match()`` or
``.hasprefix()`` call returned ``false``, return 0.
``.which()`` invokes VCL failure if: ``.which()`` invokes VCL failure if:
* The choice of ``select`` indicates failure, as documented above; that * The choice of ``element`` or ``select`` indicates failure, as
is, if ``select`` is ``UNIQUE`` or ``EXACT``, but there was no unique documented above; that is, if ``element`` is a string that is not in
or exact match, respectively. the set, or ``select`` is ``UNIQUE`` or ``EXACT``, but there was no
unique or exact match, respectively.
* There was no prior invocation of ``.match()`` or ``.hasprefix()`` in * There was no prior invocation of ``.match()`` or ``.hasprefix()`` in
the same task scope. the same task scope.
...@@ -752,6 +757,10 @@ Example:: ...@@ -752,6 +757,10 @@ Example::
} }
} }
if (myset.which(element=bereq.url) == 1) {
call do_if_the_url_was_the_first_element;
}
.. _xset.element(): .. _xset.element():
STRING xset.element(INT n, ENUM select) STRING xset.element(INT n, ENUM select)
......
...@@ -31,6 +31,11 @@ varnish v1 -vcl { ...@@ -31,6 +31,11 @@ varnish v1 -vcl {
set resp.http.Match-Zab = t.match("zab"); set resp.http.Match-Zab = t.match("zab");
set resp.http.Match-Xuuq = t.match("xuuq"); set resp.http.Match-Xuuq = t.match("xuuq");
set resp.http.Match-Raboof = t.match("raboof"); set resp.http.Match-Raboof = t.match("raboof");
set resp.http.Which-Foo = t.which(element="foo");
set resp.http.Which-Bar = t.which(element="bar");
set resp.http.Which-Baz = t.which(element="baz");
set resp.http.Which-Quux = t.which(element="quux");
set resp.http.Which-Foobar = t.which(element="foobar");
return (deliver); return (deliver);
} }
} -start } -start
...@@ -48,6 +53,11 @@ client c1 { ...@@ -48,6 +53,11 @@ client c1 {
expect resp.http.Match-Zab == "false" expect resp.http.Match-Zab == "false"
expect resp.http.Match-Xuuq == "false" expect resp.http.Match-Xuuq == "false"
expect resp.http.Match-Raboof == "false" expect resp.http.Match-Raboof == "false"
expect resp.http.Which-Foo == 1
expect resp.http.Which-Bar == 2
expect resp.http.Which-Baz == 3
expect resp.http.Which-Quux == 4
expect resp.http.Which-Foobar == 5
} -run } -run
varnish v1 -vcl { varnish v1 -vcl {
...@@ -877,9 +887,36 @@ client c1 { ...@@ -877,9 +887,36 @@ client c1 {
expect resp.reason == "VCL failed" expect resp.reason == "VCL failed"
} -run } -run
varnish v1 -vcl {
import ${vmod_selector};
backend b None;
sub vcl_init {
new s = selector.set();
s.add("foo");
s.compile();
}
sub vcl_recv {
set req.http.Which = s.which(element="bar");
}
}
client c1 {
txreq
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" { logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.matched\(2\) out of range \(1 members\)$} expect * = VCL_Error {^vmod selector failure: s\.matched\(2\) out of range \(1 members\)$}
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.which\(element="bar"\): no such element$}
expect * = VCL_return fail expect * = VCL_return fail
expect * = End expect * = End
} -run } -run
......
...@@ -689,14 +689,27 @@ select(VRT_CTX, const struct match_data * const restrict match, ...@@ -689,14 +689,27 @@ select(VRT_CTX, const struct match_data * const restrict match,
} }
VCL_INT VCL_INT
vmod_set_which(VRT_CTX, struct vmod_selector_set *set, VCL_ENUM selects) vmod_set_which(VRT_CTX, struct vmod_selector_set *set, VCL_ENUM selects,
VCL_STRING element)
{ {
struct match_data *match; struct match_data *match;
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);
if (element != NULL)
if (!vmod_set_match(ctx, TRUST_ME(set), element)) {
VFAIL(ctx, "%s.which(element=\"%s\"): no such element",
set->vcl_name, element);
return (UINT_MAX);
}
match = get_existing_match_data(ctx, set, "which"); match = get_existing_match_data(ctx, set, "which");
if (element != NULL) {
CHECK_OBJ_NOTNULL(match, MATCH_DATA_MAGIC);
assert(match->n == 1);
return (match->indices[0] + 1);
}
if (match == NULL || match->n == 0) if (match == NULL || match->n == 0)
return (0); return (0);
return (select(ctx, match, set->vcl_name, selects, "which") + 1); return (select(ctx, match, set->vcl_name, selects, "which") + 1);
......
...@@ -35,9 +35,9 @@ SYNOPSIS ...@@ -35,9 +35,9 @@ SYNOPSIS
# Match properties # Match properties
INT <obj>.nmatches() INT <obj>.nmatches()
BOOL <obj>.matched([INT n] [, STRING element] [, ENUM select]) BOOL <obj>.matched([INT n] [, STRING element] [, ENUM select])
INT <obj>.which([ENUM select]) INT <obj>.which([ENUM select] [, STRING element])
# Retrieving objects after match # Retrieving objects by index, by string, or after match
STRING <obj>.element([INT n] [, ENUM select]) STRING <obj>.element([INT n] [, ENUM select])
STRING <obj>.string([INT n] [, STRING element] [, ENUM select]) STRING <obj>.string([INT n] [, STRING element] [, ENUM select])
INT <obj>.integer([INT n] [, STRING element] [, ENUM select]) INT <obj>.integer([INT n] [, STRING element] [, ENUM select])
...@@ -663,25 +663,29 @@ Example:: ...@@ -663,25 +663,29 @@ Example::
} }
$Method INT .which(ENUM {UNIQUE, EXACT, FIRST, LAST, SHORTEST, LONGEST} $Method INT .which(ENUM {UNIQUE, EXACT, FIRST, LAST, SHORTEST, LONGEST}
select=UNIQUE) select=UNIQUE, STRING element=0)
After a successful ``.match()`` or ``.hasprefix()`` call for the same Return the index of the element indicated by ``element`` or
set object in the same task scope, return the index of the matching ``select``. The numbering corresponds to the order of ``.add()`` calls
element indicated by ``select``. The numbering corresponds to the in ``vcl_init``, starting from 1.
order of ``.add()`` calls in ``vcl_init``.
If the ``element`` parameter is set, then return the numeric index for
that string in the set.
Return 0 if the most recent ``.match()`` or ``.hasprefix()`` call If ``element`` is unset, then the index is chosen with the ``select``
returned ``false``. parameter, and refers to the previous ``.match()`` or ``.hasprefix()``
call for the same set object in the same task scope, according to the
rules given above. By default, ``select`` is ``UNIQUE``.
If more than one element matched after calling ``.hasprefix()``, the If ``element`` is unset, and the most recent ``.match()`` or
index is chosen with the ``select`` parameter, according to the rules ``.hasprefix()`` call returned ``false``, return 0.
given above. By default, ``select`` is ``UNIQUE``.
``.which()`` invokes VCL failure if: ``.which()`` invokes VCL failure if:
* The choice of ``select`` indicates failure, as documented above; that * The choice of ``element`` or ``select`` indicates failure, as
is, if ``select`` is ``UNIQUE`` or ``EXACT``, but there was no unique documented above; that is, if ``element`` is a string that is not in
or exact match, respectively. the set, or ``select`` is ``UNIQUE`` or ``EXACT``, but there was no
unique or exact match, respectively.
* There was no prior invocation of ``.match()`` or ``.hasprefix()`` in * There was no prior invocation of ``.match()`` or ``.hasprefix()`` in
the same task scope. the same task scope.
...@@ -694,6 +698,10 @@ Example:: ...@@ -694,6 +698,10 @@ Example::
} }
} }
if (myset.which(element=bereq.url) == 1) {
call do_if_the_url_was_the_first_element;
}
$Method STRING .element(INT n=0, $Method STRING .element(INT n=0,
ENUM {UNIQUE, EXACT, FIRST, LAST, SHORTEST, LONGEST} ENUM {UNIQUE, EXACT, FIRST, LAST, SHORTEST, LONGEST}
select=UNIQUE) select=UNIQUE)
......
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