Commit 7c34b94f authored by Geoff Simmons's avatar Geoff Simmons

Add the set.extract() method.

parent 44a8dbe9
......@@ -63,6 +63,8 @@ SYNOPSIS
[, ENUM select])
STRING <obj>.suball(STRING text, STRING rewrite [, INT n]
[, ENUM select])
STRING <obj>.extract(STRING text, STRING rewrite [, INT n]
[, ENUM select])
# VMOD version
STRING re2.version()
......@@ -1469,7 +1471,7 @@ set.suball(...)
)
Like the ``.sub()`` method, this returns the result of calling
``.suball(text, rewrite, fallback)`` from the regex interface for
``.suball(text, rewrite, fallback)`` from the regex interface on the
`nth` pattern added to the set, or the pattern that most recently
matched in a ``.match()`` call.
......@@ -1510,6 +1512,63 @@ Example::
}
.. _func_set.extract:
set.extract(...)
----------------
::
STRING xset.extract(
STRING text,
STRING rewrite,
STRING fallback="**EXTRACT METHOD FAILED**",
INT n=0,
ENUM {FIRST, LAST, UNIQUE} select=UNIQUE
)
Like the ``.sub()`` and ``.suball()`` methods, this method returns the
result of calling ``.extract(text, rewrite, fallback)`` from the regex
interface on the `nth` pattern added to the set, or the pattern that most
recently matched in a ``.match()`` call.
``.extract()`` is subject to the same conditions as the other rewrite
methods:
* The pattern to which it is applied is identified by ``n`` and
``select`` according to the rules given above.
* It fails if:
* The pattern that it identifies was not saved with ``.add(save=true)``.
* The values of ``n`` or ``select`` are invalid.
* The ``.extract()`` method invoked on the saved ``regex`` object
fails.
Example::
# Rewrite any URL that matches one of the patterns in the set
# by exchanging the path components.
sub vcl_init {
new matcher = re2.set(anchor=both);
matcher.add("/(foo)/(bar)/", save=true);
matcher.add("/(bar)/(baz)/", save=true);
matcher.add("/(baz)/(quux)/", save=true);
matcher.compile();
}
sub vcl_recv {
if (matcher.match(req.url)) {
if (matcher.nmatches() != 1) {
return(fail);
}
set req.url = matcher.extract(req.url, "/\2/\1/");
}
}
......
......@@ -84,6 +84,7 @@ VCL_STRING regex_rewrite_f(const struct vrt_ctx *ctx, struct vmod_re2_regex *re,
static regex_rewrite_f * const regex_rewrite[] = {
[SUB] = vmod_regex_sub,
[SUBALL] = vmod_regex_suball,
[EXTRACT] = vmod_regex_extract,
};
static inline int
......@@ -547,6 +548,14 @@ vmod_set_suball(VRT_CTX, struct vmod_re2_set *set, VCL_STRING text,
return rewritef(ctx, set, text, rewrite, fallback, n, selects, SUBALL);
}
VCL_STRING
vmod_set_extract(VRT_CTX, struct vmod_re2_set *set, VCL_STRING text,
VCL_STRING rewrite, VCL_STRING fallback, VCL_INT n,
VCL_ENUM selects)
{
return rewritef(ctx, set, text, rewrite, fallback, n, selects, EXTRACT);
}
VCL_STRING
vmod_set_string(VRT_CTX, struct vmod_re2_set *set, VCL_INT n, VCL_ENUM selects)
{
......
# looks like -*- vcl -*-
varnishtest "set.extract() method"
varnish v1 -vcl {
import ${vmod_re2};
backend be { .host = "${bad_ip}"; }
sub vcl_init {
new s = re2.set();
s.add("(.*)@([^.]*)", save=true);
s.add(".*", save=true);
s.compile();
new n = re2.set();
n.add("(.*)@([^.]*)");
n.add(".*", save=true);
n.compile();
}
sub vcl_recv {
return(synth(200));
}
sub vcl_synth {
# cf. extract.vtc
set resp.http.uucp = s.extract("boris@kremvax.ru", "\2!\1",
n=1);
set resp.http.quote = s.extract("foo", "'\0'", n=2);
set resp.http.fail = s.extract("foo", "bar", "fallback", n=1);
set resp.http.undeffallback
= s.extract("foo", "bar", req.http.undef, n=1);
set resp.http.undeftext
= s.extract(req.http.undef, "x", "text undef", n=1);
set resp.http.undefrewrite
= s.extract("b", req.http.undef, "rewrite undef", n=1);
set resp.http.s-match = s.match("boris@kremvax.ru");
set resp.http.s-nmatches = s.nmatches();
set resp.http.s-extract
= s.extract("boris@kremvax.ru", "\2!\1");
set resp.http.s-first
= s.extract("boris@kremvax.ru", "\2!\1", select=FIRST);
set resp.http.s-last
= s.extract("boris@kremvax.ru", "\2!\1", select=LAST);
set resp.http.n-match = n.match("boris@kremvax.ru");
set resp.http.n-n = n.nmatches();
set resp.http.n-extract
= n.extract("boris@kremvax.ru", "\2!\1");
set resp.http.n-first
= n.extract("boris@kremvax.ru", "\2!\1", select=FIRST);
set resp.http.n-last
= n.extract("boris@kremvax.ru", "\2!\1", select=LAST);
}
} -start
client c1 {
txreq
rxresp
expect resp.http.uucp == "kremvax!boris"
expect resp.http.quote == "'foo'"
expect resp.http.fail == "fallback"
expect resp.http.undeffallback == "**EXTRACT METHOD FAILED**"
expect resp.http.undeftext == "text undef"
expect resp.http.undefrewrite == "rewrite undef"
expect resp.http.s-match == "true"
expect resp.http.s-nmatches == "2"
expect resp.http.s-extract == ""
expect resp.http.s-first == "kremvax!boris"
expect resp.http.s-last == "!"
expect resp.http.n-match == "true"
expect resp.http.n-n == "2"
expect resp.http.n-extract == ""
expect resp.http.n-first == ""
expect resp.http.n-last == "!"
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error "^vmod re2 error: s_..extract..: fallback is undefined$"
expect * = VCL_Error "^vmod re2 error: s_..extract.text=<undefined>, fallback=.text undef..: text is undefined$"
expect * = VCL_Error "^vmod re2 error: s_..extract.text=.b., rewrite=<undefined>, fallback=.rewrite undef..: rewrite is undefined$"
expect * = VCL_Error "^vmod re2 error: s.extract.0.: 2 successful matches$"
expect * = VCL_Error "^vmod re2 error: n.extract.boris@kremvax.ru, .2!.1, 0, FIRST.: Pattern 1 was not saved$"
expect * = End
} -run
......@@ -52,6 +52,8 @@ SYNOPSIS
[, ENUM select])
STRING <obj>.suball(STRING text, STRING rewrite [, INT n]
[, ENUM select])
STRING <obj>.extract(STRING text, STRING rewrite [, INT n]
[, ENUM select])
# VMOD version
STRING re2.version()
......@@ -1189,7 +1191,7 @@ $Method STRING .suball(STRING text, STRING rewrite,
INT n=0, ENUM {FIRST, LAST, UNIQUE} select=UNIQUE)
Like the ``.sub()`` method, this returns the result of calling
``.suball(text, rewrite, fallback)`` from the regex interface for
``.suball(text, rewrite, fallback)`` from the regex interface on the
`nth` pattern added to the set, or the pattern that most recently
matched in a ``.match()`` call.
......@@ -1229,6 +1231,51 @@ Example::
}
}
$Method STRING .extract(STRING text, STRING rewrite,
STRING fallback="**EXTRACT METHOD FAILED**",
INT n=0, ENUM {FIRST, LAST, UNIQUE} select=UNIQUE)
Like the ``.sub()`` and ``.suball()`` methods, this method returns the
result of calling ``.extract(text, rewrite, fallback)`` from the regex
interface on the `nth` pattern added to the set, or the pattern that most
recently matched in a ``.match()`` call.
``.extract()`` is subject to the same conditions as the other rewrite
methods:
* The pattern to which it is applied is identified by ``n`` and
``select`` according to the rules given above.
* It fails if:
* The pattern that it identifies was not saved with ``.add(save=true)``.
* The values of ``n`` or ``select`` are invalid.
* The ``.extract()`` method invoked on the saved ``regex`` object
fails.
Example::
# Rewrite any URL that matches one of the patterns in the set
# by exchanging the path components.
sub vcl_init {
new matcher = re2.set(anchor=both);
matcher.add("/(foo)/(bar)/", save=true);
matcher.add("/(bar)/(baz)/", save=true);
matcher.add("/(baz)/(quux)/", save=true);
matcher.compile();
}
sub vcl_recv {
if (matcher.match(req.url)) {
if (matcher.nmatches() != 1) {
return(fail);
}
set req.url = matcher.extract(req.url, "/\2/\1/");
}
}
$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