# network-uri-template
Library for parsing and expanding URI Templates, as per [RFC 6570][rfc6570].
[rfc6570]: https://datatracker.ietf.org/doc/html/rfc6570
## URI Templates
An example from the RFC:
> For example, the following URI Template includes a form-style
> parameter expression, as indicated by the "?" operator appearing
> before the variable names.
>
> ```
> http://www.example.com/foo{?query,number}
> ```
>
> The expansion process for expressions beginning with the question-
> mark ("?") operator follows the same pattern as form-style interfaces
> on the World Wide Web:
>
> ```
> http://www.example.com/foo{?query,number}
> \_____________/
> |
> |
> For each defined variable in [ 'query', 'number' ],
> substitute "?" if it is the first substitution or "&"
> thereafter, followed by the variable name, '=', and the
> variable's value.
> ```
>
> If the variables have the values
>
> ```
> query := "mycelium"
> number := 100
> ```
>
> then the expansion of the above URI Template is
>
> ```
> http://www.example.com/foo?query=mycelium&number=100
> ```
>
> Alternatively, if 'query' is undefined, then the expansion would be
>
> ```
> http://www.example.com/foo?number=100
> ```
>
> or if both variables are undefined, then it would be
>
> ```
> http://www.example.com/foo
> ```
For a complete description of URI Templates, consult the RFC or see our
extracted [test cases][examples].
[examples]: rfc/examples.txt
## Example
```haskell
{-# LANGUAGE OverloadedStrings #-}
module Main
( main
) where
import Prelude
import Data.Text (Text)
import Data.Text.IO qualified as T
import Data.Map.Strict (Map)
import Data.Map.Strict qualified as Map
import Network.URI.Template
import System.Exit (die)
main :: IO ()
main = do
let
vars :: Map VarName VarValue
vars =
Map.fromList
[ ("query", "mycelium")
, ("number", "100")
]
template :: Text
template = "http://www.example.com/foo{?query,number}"
handle = either (die . templateErrorPretty) T.putStrLn
handle $ processTemplate vars template
-- => http://www.example.com/foo?query=mycelium&number=100
handle $ processTemplate (Map.delete "query" vars) template
-- => http://www.example.com/foo?number=100
handle $ processTemplate (Map.empty) template
-- => http://www.example.com/foo
```
## CLI
This project includes a small CLI to experiment with template expansion.
```console
network-uri-template \
--var 'query := "mycelium"' \
--var 'number := "100"' \
--var 'path := ("foo", "bar")' \
--var 'keys := [("sort","asc"), ("page","2")]' \
'http://www.example.com{/path*}/foo{?query:2,number}{&keys*}'
```

## License
This project is licensed AGPLv3. See [COPYING](./COPYING).