Commit 61dfec02 authored by Geoff Simmons's avatar Geoff Simmons

Add the element parameter to .matched().

parent 44080166
......@@ -38,7 +38,7 @@ SYNOPSIS
# Match properties
INT <obj>.nmatches()
BOOL <obj>.matched([INT n] [, ENUM select])
BOOL <obj>.matched([INT n] [, STRING element] [, ENUM select])
INT <obj>.which([ENUM select])
# Retrieving objects after match
......@@ -618,59 +618,74 @@ Example::
.. _xset.matched():
BOOL xset.matched(INT n, ENUM select)
-------------------------------------
BOOL xset.matched(INT n, STRING element, ENUM select)
-----------------------------------------------------
::
BOOL xset.matched(
INT n=0,
STRING element=0,
ENUM {UNIQUE, EXACT, FIRST, LAST, SHORTEST, LONGEST} select=UNIQUE
)
After a successful ``.match()`` or ``.hasprefix()`` call for the same
set object in the same task scope, return ``true`` if the element
indicated by the ``n`` and ``select`` parameters was matched, according to
the rules described above.
indicated by the ``n``, ``element`` and ``select`` parameters was
matched, according to the rules described above.
For example if ``n`` > 0, ``.matched(n)`` returns ``true`` if and only
if the ``n``-th element matched. The numbering corresponds to the
order of ``.add()`` invocations in ``vcl_init`` (starting from 1). The
``select`` parameter is ignored in this case.
If ``n`` <= 0, the set element is determined by the ``select`` enum.
In that case, ``.matched()`` returns ``true`` if and only if the
element indicated by the enum was matched by the previous successful
match operation. These distinctions are only relevant if the previous
operation was ``.hasprefix()``, and more than one string was matched
due to overlapping prefixes. ``.matched()`` returns ``true`` for all
values of ``select`` if the previous successful operation was
``.match()``. ``n`` defaults to 0, so the ``n`` parameter can be left
out if the use of ``select`` is intended.
If ``n`` <= 0 and ``select`` is ``UNIQUE`` or ``EXACT``, then
``.matched()`` returns ``true`` if the enum's criteria are met;
otherwise it returns ``false``, and does not fail. This can be used as
a safeguard for the methods described below, which invoke VCL failure
if either of these two enums are specified, but their criteria are not
met.
``select`` and ``element`` parameters are ignored in this case.
If ``n`` <= 0 and ``element`` is set, then ``.matched()`` returns
``true`` if and only if the string specified by ``element`` was
matched in the previous successful ``.match()`` or ``.hasprefix()``
call. If ``element`` is not in the set, then ``.matched()`` does not
invoke VCL failure (this is a deviation from the general rules for
``element``), but ``.matched()`` always returns ``false`` in that
case. Thus ``.matched()`` can always used with ``element`` to safely
check if a string was previously matched, regardless of whether the
string is in the set.
``n`` defaults to 0, so the ``n`` parameter can be left out if
``element`` is set.
If ``n`` <= 0 and ``element`` is unset, the set element is determined
by the ``select`` enum. In that case, ``.matched()`` returns ``true``
if and only if the element indicated by the enum was matched by the
previous successful match operation. These distinctions are only
relevant if the previous operation was ``.hasprefix()``, and more than
one string was matched due to overlapping prefixes. ``.matched()``
returns ``true`` for all values of ``select`` if the previous
successful operation was ``.match()``.
``n`` defaults to 0 and ``element`` is unset by default, so the ``n``
and ``element`` parameters can be left out if the use of ``select`` is
intended.
If ``n`` <= 0, ``element`` is unset, and ``select`` is ``UNIQUE`` or
``EXACT``, then ``.matched()`` returns ``true`` if the enum's criteria
are met; otherwise it returns ``false``, and does not fail. This can
be used as a safeguard for the methods described below, which invoke
VCL failure if either of these two enums are specified, but their
criteria are not met.
The other enum values (``FIRST``, ``LAST``, ``SHORTEST`` and
``LONGEST``) are included for consistency with the other methods, but
they don't make a relevant distinction. If the prior invocation of
``.match()`` or ``.hasprefix()`` was successful (returned ``true``),
then ``.matched()`` returns ``true`` for each of these, since there is
always an element that meets the criteria. If the prior invocation was
unsuccessful, ``.matched()`` always returns ``false`` for each of the
four enums.
always an element that meets the criteria.
``.matched()`` always returns ``false`` if the most recent
``.match()`` or ``.hasprefix()`` call returned ``false``.
``.matched()`` invokes VCL failure if:
* The parameter is out of range -- greater than the number of elements
in the set.
* The ``n`` parameter is out of range -- greater than the number of
elements in the set.
* There was no prior invocation of ``.match()`` or ``.hasprefix()`` in
the same task scope.
......@@ -689,6 +704,12 @@ Example::
}
}
if (url_prefixes.hasprefix(bereq.url)) {
if (urls.matched(element="/foo/")) {
call do_if_foo_was_matched;
}
}
.. _xset.which():
INT xset.which(ENUM select)
......@@ -1059,10 +1080,10 @@ failure is invoked. VCL failure has the same results as if
VCL failure is meant to "fail fast" on conditions that cannot be
correct, or when resource limitations such as workspace exhaustion
prevent further processing. Depending on your use case, you may be
able to use the VMOD's methods without risk of failure. For example,
if it is known that none of the strings in a set have common prefixes,
then methods with ``select=UNIQUE`` can be used safely after calling
``.hasprefix()``.
able to use the VMOD's methods without additional checking and with no
risk of failure. For example, if it is known that none of the strings
in a set have common prefixes, then methods with ``select=UNIQUE`` can
be used safely after calling ``.hasprefix()``.
If you need to check against possible failure conditions:
......@@ -1075,6 +1096,12 @@ If you need to check against possible failure conditions:
ensure that VCL load fails if a set unintentionally has strings
with common prefixes.
* In most cases, a method invokes VCL failure if the value of the
``element`` parameter is not in the set. But ``element`` can be used
safely with any string in ``.matched()`` to check if a string
matched previously -- ``.matched()`` returns ``false`` if the
``element`` is not in the set.
See `LIMITATIONS`_ for considerations if you encounter conditions such
as workspace exhaustion.
......
......@@ -837,12 +837,16 @@ varnish v1 -vcl {
set resp.http.Matched-Last = s.matched(select=LAST);
set resp.http.Matched-Shortest = s.matched(select=SHORTEST);
set resp.http.Matched-Longest = s.matched(select=LONGEST);
set resp.http.Matched-Foo = s.matched(element="foo");
set resp.http.Matched-Baz = s.matched(element="baz");
set resp.http.Non-Match = s.hasprefix("baz");
set resp.http.Non-Matched-First = s.matched(select=FIRST);
set resp.http.Non-Matched-Last = s.matched(select=LAST);
set resp.http.Non-Matched-Shortest = s.matched(select=SHORTEST);
set resp.http.Non-Matched-Longest = s.matched(select=LONGEST);
set resp.http.Non-Matched-Foo = s.matched(element="foo");
set resp.http.Non-Matched-Baz = s.matched(element="baz");
return (deliver);
}
......@@ -857,11 +861,15 @@ client c1 {
expect resp.http.Matched-Last == "true"
expect resp.http.Matched-Shortest == "true"
expect resp.http.Matched-Longest == "true"
expect resp.http.Matched-Foo == "true"
expect resp.http.Matched-Baz == "false"
expect resp.http.Non-Match == "false"
expect resp.http.Non-Matched-First == "false"
expect resp.http.Non-Matched-Last == "false"
expect resp.http.Non-Matched-Shortest == "false"
expect resp.http.Non-Matched-Longest == "false"
expect resp.http.Non-Matched-Foo == "false"
expect resp.http.Non-Matched-Baz == "false"
txreq -hdr "Range-Error: oops"
rxresp
......
......@@ -606,7 +606,7 @@ vmod_set_nmatches(VRT_CTX, struct vmod_selector_set *set)
VCL_BOOL
vmod_set_matched(VRT_CTX, struct VPFX(selector_set) *set, VCL_INT idx,
VCL_ENUM selects)
VCL_STRING element, VCL_ENUM selects)
{
struct match_data *match;
......@@ -636,6 +636,14 @@ vmod_set_matched(VRT_CTX, struct VPFX(selector_set) *set, VCL_INT idx,
return (0);
}
if (element != NULL) {
for (unsigned i = 0; i < match->n; i++)
if (strcmp(set->members[match->indices[i]], element)
== 0)
return (1);
return (0);
}
if (selects == VENUM(UNIQUE))
return (match->n == 1);
if (selects == VENUM(EXACT))
......
......@@ -34,7 +34,7 @@ SYNOPSIS
# Match properties
INT <obj>.nmatches()
BOOL <obj>.matched([INT n] [, ENUM select])
BOOL <obj>.matched([INT n] [, STRING element] [, ENUM select])
INT <obj>.which([ENUM select])
# Retrieving objects after match
......@@ -575,53 +575,67 @@ Example::
set bereq.backend = myset.backend(select=UNIQUE);
}
$Method BOOL .matched(INT n=0,
$Method BOOL .matched(INT n=0, STRING element=0,
ENUM {UNIQUE, EXACT, FIRST, LAST, SHORTEST, LONGEST}
select=UNIQUE)
After a successful ``.match()`` or ``.hasprefix()`` call for the same
set object in the same task scope, return ``true`` if the element
indicated by the ``n`` and ``select`` parameters was matched, according to
the rules described above.
indicated by the ``n``, ``element`` and ``select`` parameters was
matched, according to the rules described above.
For example if ``n`` > 0, ``.matched(n)`` returns ``true`` if and only
if the ``n``-th element matched. The numbering corresponds to the
order of ``.add()`` invocations in ``vcl_init`` (starting from 1). The
``select`` parameter is ignored in this case.
If ``n`` <= 0, the set element is determined by the ``select`` enum.
In that case, ``.matched()`` returns ``true`` if and only if the
element indicated by the enum was matched by the previous successful
match operation. These distinctions are only relevant if the previous
operation was ``.hasprefix()``, and more than one string was matched
due to overlapping prefixes. ``.matched()`` returns ``true`` for all
values of ``select`` if the previous successful operation was
``.match()``. ``n`` defaults to 0, so the ``n`` parameter can be left
out if the use of ``select`` is intended.
If ``n`` <= 0 and ``select`` is ``UNIQUE`` or ``EXACT``, then
``.matched()`` returns ``true`` if the enum's criteria are met;
otherwise it returns ``false``, and does not fail. This can be used as
a safeguard for the methods described below, which invoke VCL failure
if either of these two enums are specified, but their criteria are not
met.
``select`` and ``element`` parameters are ignored in this case.
If ``n`` <= 0 and ``element`` is set, then ``.matched()`` returns
``true`` if and only if the string specified by ``element`` was
matched in the previous successful ``.match()`` or ``.hasprefix()``
call. If ``element`` is not in the set, then ``.matched()`` does not
invoke VCL failure (this is a deviation from the general rules for
``element``), but ``.matched()`` always returns ``false`` in that
case. Thus ``.matched()`` can always used with ``element`` to safely
check if a string was previously matched, regardless of whether the
string is in the set.
``n`` defaults to 0, so the ``n`` parameter can be left out if
``element`` is set.
If ``n`` <= 0 and ``element`` is unset, the set element is determined
by the ``select`` enum. In that case, ``.matched()`` returns ``true``
if and only if the element indicated by the enum was matched by the
previous successful match operation. These distinctions are only
relevant if the previous operation was ``.hasprefix()``, and more than
one string was matched due to overlapping prefixes. ``.matched()``
returns ``true`` for all values of ``select`` if the previous
successful operation was ``.match()``.
``n`` defaults to 0 and ``element`` is unset by default, so the ``n``
and ``element`` parameters can be left out if the use of ``select`` is
intended.
If ``n`` <= 0, ``element`` is unset, and ``select`` is ``UNIQUE`` or
``EXACT``, then ``.matched()`` returns ``true`` if the enum's criteria
are met; otherwise it returns ``false``, and does not fail. This can
be used as a safeguard for the methods described below, which invoke
VCL failure if either of these two enums are specified, but their
criteria are not met.
The other enum values (``FIRST``, ``LAST``, ``SHORTEST`` and
``LONGEST``) are included for consistency with the other methods, but
they don't make a relevant distinction. If the prior invocation of
``.match()`` or ``.hasprefix()`` was successful (returned ``true``),
then ``.matched()`` returns ``true`` for each of these, since there is
always an element that meets the criteria. If the prior invocation was
unsuccessful, ``.matched()`` always returns ``false`` for each of the
four enums.
always an element that meets the criteria.
``.matched()`` always returns ``false`` if the most recent
``.match()`` or ``.hasprefix()`` call returned ``false``.
``.matched()`` invokes VCL failure if:
* The parameter is out of range -- greater than the number of elements
in the set.
* The ``n`` parameter is out of range -- greater than the number of
elements in the set.
* There was no prior invocation of ``.match()`` or ``.hasprefix()`` in
the same task scope.
......@@ -640,6 +654,12 @@ Example::
}
}
if (url_prefixes.hasprefix(bereq.url)) {
if (urls.matched(element="/foo/")) {
call do_if_foo_was_matched;
}
}
$Method INT .which(ENUM {UNIQUE, EXACT, FIRST, LAST, SHORTEST, LONGEST}
select=UNIQUE)
......@@ -943,10 +963,10 @@ failure is invoked. VCL failure has the same results as if
VCL failure is meant to "fail fast" on conditions that cannot be
correct, or when resource limitations such as workspace exhaustion
prevent further processing. Depending on your use case, you may be
able to use the VMOD's methods without risk of failure. For example,
if it is known that none of the strings in a set have common prefixes,
then methods with ``select=UNIQUE`` can be used safely after calling
``.hasprefix()``.
able to use the VMOD's methods without additional checking and with no
risk of failure. For example, if it is known that none of the strings
in a set have common prefixes, then methods with ``select=UNIQUE`` can
be used safely after calling ``.hasprefix()``.
If you need to check against possible failure conditions:
......@@ -959,6 +979,12 @@ If you need to check against possible failure conditions:
ensure that VCL load fails if a set unintentionally has strings
with common prefixes.
* In most cases, a method invokes VCL failure if the value of the
``element`` parameter is not in the set. But ``element`` can be used
safely with any string in ``.matched()`` to check if a string
matched previously -- ``.matched()`` returns ``false`` if the
``element`` is not in the set.
See `LIMITATIONS`_ for considerations if you encounter conditions such
as workspace exhaustion.
......
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