.. _library_uri_template:

``uri_template``
================

This library implements URI template validation, variable enumeration,
and expansion as specified by RFC 6570. It supports all four template
levels, including all defined operators, prefix modifiers, and exploded
list and associative-array values.

The predicates are defined in the ``uri_template(_Representation_)``
parametric object, where ``_Representation_`` must be one of:

- ``atom`` - text is represented by atoms
- ``chars`` - text is represented by lists of characters
- ``codes`` - text is represented by lists of character codes

API documentation
-----------------

Open the
`../../apis/library_index.html#uri-template <../../apis/library_index.html#uri-template>`__
link in a web browser.

Loading
-------

To load all entities in this library, load the ``loader.lgt`` file:

::

   | ?- logtalk_load(uri_template(loader)).

Testing
-------

To test this library predicates, load the ``tester.lgt`` file:

::

   | ?- logtalk_load(uri_template(tester)).

The test suite includes the complete RFC 6570 example matrix, ported to
run with all three supported text representations. ASCII tests are
shared by all backends. Unicode tests are kept in a separate file and
are included only when the backend reports Unicode support.

Bindings
--------

The ``expand/3`` predicate accepts a list of unique ``Name-Value``
pairs. Names and all textual values use the object representation.
Values use one of these explicit forms:

- ``undefined``
- ``string(Text)``
- ``list(Texts)``
- ``assoc(NameValuePairs)``
- ``structure(NameValuePairs)``

List members and association values may be ``undefined``. Missing
bindings are also undefined. An empty string is defined, while an empty
list or association is undefined. Prefix modifiers are only applicable
to string values.

Structured values may contain nested ``structure/1`` values. They are
processed as associative arrays, with dots separating nested field names
as specified by RFC 6570.

Explicit constructors are necessary because, with ``chars`` and
``codes``, both an empty text value and an empty composite value would
otherwise be represented by the empty list.

Usage
-----

::

   | ?- uri_template(atom)::valid('http://example.com/search{?q,lang}').
   true.

   | ?- uri_template(atom)::variables('{x}{?y,x,list*}', Variables).
   Variables = [x, y, list].

   | ?- uri_template(atom)::expand(
            'http://example.com/search{?q,lang}',
            [q-string('URI templates'), lang-string(en)],
            URI
        ).
   URI = 'http://example.com/search?q=URI%20templates&lang=en'.

   | ?- uri_template(atom)::expand(
            '/colors{/colors*}',
            [colors-list([red, green, blue])],
            URI
        ).
   URI = '/colors/red/green/blue'.

   | ?- uri_template(atom)::expand(
            '/search{?parameters*}',
            [parameters-assoc([q-'URI templates', page-'2'])],
            URI
        ).
   URI = '/search?q=URI%20templates&page=2'.

Variable names are case-sensitive. Percent-encoded triplets in variable
names are preserved and are not decoded for binding lookup. Non-ASCII
expansion data is encoded as UTF-8 before percent encoding. The library
does not normalize Unicode; callers should apply NFC normalization to
user-provided text when appropriate, as recommended by RFC 6570.

The ``expand/4`` predicate provides diagnostic expansion. It returns
syntax errors as zero-based ``error(Position, Reason)`` terms while
preserving malformed template text according to the recovery
recommendations in RFC 6570. The possible reasons are
``malformed_expression``, ``unterminated_expression``, and
``invalid_literal``.
