taler-docs

Documentation for GNU Taler components, APIs and protocols
Log | Files | Refs | README | LICENSE

commit 5ec27b75c8ac9411d9f0ea8eddbe8b4238d52fd7
parent 700a7116309c355f1557b841356e826b6d4c34de
Author: Christian Grothoff <christian@grothoff.org>
Date:   Wed,  5 Aug 2026 21:31:22 +0200

document paivana regex matching

Diffstat:
Mfrags/paivana-httpd-manual.rst | 51+++++++++++++++++++++++++++++++++++++++++++++++----
Mmanpages/paivana.conf.5.rst | 5+++++
2 files changed, 52 insertions(+), 4 deletions(-)

diff --git a/frags/paivana-httpd-manual.rst b/frags/paivana-httpd-manual.rst @@ -361,8 +361,25 @@ upstream: A few details worth knowing: - The expression is matched against the URL path only, not against the - host or the request method. A match anywhere in the path counts, so - anchor with ``^`` and ``$`` if you mean "the whole path". + host or the request method. +- The expression must match the path in its **entirety**. + ``paivana-httpd`` anchors it for you — it compiles ``^(`` *your + expression* ``)$``, so writing your own ``^`` and ``$`` is harmless + but redundant. What this rules out is a substring match: + ``/assets/`` on its own whitelists nothing, because no path is + exactly that; ``/assets/.*`` is what whitelists that subtree. The + enclosing group matters for alternations: ``a|b`` behaves as + "exactly ``a`` or exactly ``b``", not as "starts with ``a`` or ends + with ``b``". +- Anchoring is a safety property, not a convenience. An unanchored + whitelist grants free access to every path merely *containing* the + expression, which a client can arrange deliberately: with a + substring rule, a request for ``/premium/article?x=/robots.txt`` + would sail past the paywall. +- Paths longer than 16 kb are rejected outright with HTTP ``414 URI + Too Long``, before any expression is evaluated. The cap bounds the + cost of a pathological expression on a path an unpaying client + controls; no legitimate URL comes close to it. - An invalid regular expression is a fatal configuration error: ``paivana-httpd`` logs the problem and refuses to start. - The internal endpoints ``POST /.well-known/paivana`` (payment @@ -505,6 +522,32 @@ entry in ``choices`` describes one way the client may pay and is an :ts:type:`OrderChoice` object (so the paywall can also support the use of subscription tokens, discount coupons, etc.). +Two properties of the matching are easy to get wrong, and both make +the difference between a template that applies and one that silently +never does: + +- The subject is the **absolute URL**, not the path. It is the + configured ``BASE_URL`` (or the scheme and ``Host`` of the request, + when ``BASE_URL`` is not set) followed by the path — for example + ``https://example.com/premium/article``. An expression written + against the path alone, such as ``/premium/.*``, therefore matches + nothing. +- The expression must match that URL in its **entirety**. + ``paivana-httpd`` anchors it for you, compiling ``^(`` *your + expression* ``)$``, so a substring rule does not apply to the URLs + containing it. Writing your own ``^`` and ``$`` remains harmless. + The enclosing group means an alternation such as ``a|b`` is read as + "exactly ``a`` or exactly ``b``". + +So a template meant for one subtree is written either against the +whole URL, ``https://example\.com/premium/.*``, or with a leading +wildcard, ``.*/premium/.*``, if the same template should apply +regardless of the host the site is served under. + +A URL longer than 16 kb is answered with HTTP ``414 URI Too Long`` +and no template is evaluated for it. The cap bounds the cost of a +pathological expression on a URL an unpaying client controls. + A successful create returns HTTP ``204 No Content``. After creating the template, (re)start ``paivana-httpd`` so that it re-reads the template list: @@ -536,7 +579,7 @@ and 50 cents (``KUDOS:0.5``) for standard articles: "template_contract": { "template_type": "paivana", "summary": "Premium article on example.com", - "website_regex": "^/premium/.*", + "website_regex": ".*/premium/.*", "choices": [ { "amount": "KUDOS:2" } ] } }' @@ -550,7 +593,7 @@ and 50 cents (``KUDOS:0.5``) for standard articles: "template_contract": { "template_type": "paivana", "summary": "Standard article on example.com", - "website_regex": "^/standard/.*", + "website_regex": ".*/standard/.*", "choices": [ { "amount": "KUDOS:0.5" } ] } }' diff --git a/manpages/paivana.conf.5.rst b/manpages/paivana.conf.5.rst @@ -143,6 +143,11 @@ WHITELIST Whitelisted paths are never subject to the paywall. Should be used to whitelist resources such as images or style sheets. Paths matched against the whitelist always start with '/'. + The expression must match the path in its **entirety**: + it is anchored at both ends before it is compiled, so + ``/assets/`` whitelists nothing and ``/assets/.*`` is + needed to whitelist that subtree. Paths longer than + 16 kb are rejected with HTTP 414 rather than matched. This setting is optional. SEE ALSO