uri-templater-0.3.1.0: Parsing & Quasiquoting for RFC 6570 URI Templates

Safe HaskellNone
LanguageHaskell98

Network.URI.Template

Contents

Description

RFC 6570 URI templates are a convenient mechanism for constructing URIs in a standardized way. They provide the ability to escape the interpolated values appropriately, format them for the appropriate part of the URI, and can handle list-like ([], Vector) and associative inputs (such as associative lists, Maps, HashMaps).

This implementation supports outputting these URI fragments to all widely-used textual/bytestring formats, and provides basic facilities for extending the URI rendering to support other output formats.

Synopsis

Documentation

Due to the large number of different interpolation options available, it is arguably easiest to view an example of each sort of interpolation to see how it works. RFC 6570 itself https://tools.ietf.org/html/rfc6570 also provides a large number of these same examples, so it may help to look at it directly.

For these examples, the following values are assumed:

var :: TemplateString
var = "value"

semi :: TemplateString
semi = ";"

hello :: TemplateString
hello = "Hello World!"

path :: TemplateString
path = "/foo/bar"

list :: [TemplateString]
list = ["red", "green", "blue"]

keys :: AList TemplateString TemplateString
keys = AList [("semi", ";"), ("dot", "."), ("comma", ",")]

Simple interpolation

Simple string expansion is the default expression type when no operator is given.

For each defined variable in the variable-list, perform variable expansion. If more than one variable has a defined value, append a comma (",") to the result string as a separator between variable expansions.

Without modifiers

>>> [uri|{var}|]
value

Interpolating with a length modifier

>>> [uri|{var:3}|]
val

Interpolating multiple values:

>>> [uri|{var,hello}|]
value,hello

Interpolating a list:

>>> [uri|{list}|]
red,green,blue

Exploding a list (not super useful without modifiers):

>>> [uri|{list*}|]
red,green,blue

Interpolating associative values:

>>> [uri|{keys}|]
semi,%3B,dot,.,comma,%2C

Exploding associative values

>>> [uri|{keys*}|]
semi=%3B,dot=.,comma=%2C

Unescaped interpolation

>>> [uri|{+path:6}/here|]
/foo/b/here
>>> [uri|{+list}|]
red,green,blue
>>> [uri|{+list*}|]
red,green,blue
>>> [uri|{+keys}]
semi,;,dot,.,comma,,
>>> [uri|{+keys*}]
semi=;,dot=.,comma=,

Path piece interpolation

Path segment expansion, as indicated by the slash ("/"), is useful for describing URI path hierarchies.

For each defined variable in the variable-list, append "/" to the result string and then perform variable expansion.

Note that the expansion process for path segment expansion is identical to that of label expansion aside from the substitution of "" instead of ".". However, unlike ".", a "" is a reserved character and will be percent-encoded if found in a value.

>>> [uri|{/var:1,var}|]
/v/value
>>> [uri|{/list}|]
/red,green,blue
>>> [uri|{/list*}]
/red/green/blue

Query param interpolation

>>> [uri|{?var:3}|]
?var=val
>>> [uri|{?list}|]
?list=red,green.blue
>>> [uri|{?list*}|]
?list=red&list=green&list=blue
>>> [uri|{?keys}|]
?keys=semi,%3B,dot,.,comma,%2C
>>> [uri|{?keys*}|]
?semi=%3B&dot=.&comma=%2C

Continued query param interpolation

>>> [uri|{?var:3}|]
&var=val
>>> [uri|{?list}|]
&list=red,green.blue
>>> [uri|{?list*}|]
&list=red&list=green&list=blue
>>> [uri|{?keys}|]
&keys=semi,%3B,dot,.,comma,%2C
>>> [uri|{?keys*}|]
&semi=%3B&dot=.&comma=%2C

Label interpolation

Label expansion, as indicated by the dot (".") operator is useful for describing URI spaces with varying domain names or path selectors (e.g., filename extensions).

>>> [uri|X{.var:3}|]
X.val
>>> [uri|X{.list}|]
X.red,green,blue
>>> [uri|X{.list*}|]
X.red.green.blue
>>> [uri|X{.keys}|]
X.semi,%3B,dot,.,comma,%2C
>>> [uri|X{.keys*}|]
X.semi=%3B.dot=..comma=%2C

Fragment interpolation

Path-style parameter expansion, as indicated by the semicolon (";") is useful for describing URI path parameters, such as "path;property" or "path;name=value".

>>> [uri|{;hello:5}|]
;hello=Hello
>>> [uri|{;list}|]
;list=red,green,blue
>>> [uri|{;list*}|]
;list=red;list=green;list=blue
>>> [uri|{;keys}|]
;keys=semi,%3B,dot,.,comma,%2C
>>> [uri|{;keys*}|]
;semi=%3B;dot=.;comma=%2C

Security Considerations

A URI Template does not contain active or executable content. However, it might be possible to craft unanticipated URIs if an attacker is given control over the template or over the variable values within an expression that allows reserved characters in the expansion. In either case, the security considerations are largely determined by who provides the template, who provides the values to use for variables within the template, in what execution context the expansion occurs (client or server), and where the resulting URIs are used.

Quasi-Quoting URI templates

uri :: QuasiQuoter #

URI quasiquoter. Can only be used in expressions, not for top-level declarations

Manually parsing, constructing, & writing URI templates

render :: Buildable str => UriTemplate -> [BoundValue] -> str #

class ToTemplateValue a where #

Minimal complete definition

toTemplateValue

Associated Types

type TemplateRep a :: * #

Instances

ToTemplateValue Bool # 

Associated Types

type TemplateRep Bool :: * #

ToTemplateValue Double # 

Associated Types

type TemplateRep Double :: * #

ToTemplateValue Float # 

Associated Types

type TemplateRep Float :: * #

ToTemplateValue Int # 

Associated Types

type TemplateRep Int :: * #

ToTemplateValue Int8 # 

Associated Types

type TemplateRep Int8 :: * #

ToTemplateValue Int16 # 

Associated Types

type TemplateRep Int16 :: * #

ToTemplateValue Int32 # 

Associated Types

type TemplateRep Int32 :: * #

ToTemplateValue Int64 # 

Associated Types

type TemplateRep Int64 :: * #

ToTemplateValue Integer # 
ToTemplateValue Natural # 
ToTemplateValue Ordering # 
ToTemplateValue Word # 

Associated Types

type TemplateRep Word :: * #

ToTemplateValue Word8 # 

Associated Types

type TemplateRep Word8 :: * #

ToTemplateValue Word16 # 

Associated Types

type TemplateRep Word16 :: * #

ToTemplateValue Word32 # 

Associated Types

type TemplateRep Word32 :: * #

ToTemplateValue Word64 # 

Associated Types

type TemplateRep Word64 :: * #

ToTemplateValue () # 

Associated Types

type TemplateRep () :: * #

ToTemplateValue Text # 

Associated Types

type TemplateRep Text :: * #

ToTemplateValue Text # 

Associated Types

type TemplateRep Text :: * #

ToTemplateValue Version # 
ToTemplateValue All # 

Associated Types

type TemplateRep All :: * #

ToTemplateValue Any # 

Associated Types

type TemplateRep Any :: * #

ToTemplateValue ZonedTime # 
ToTemplateValue LocalTime # 
ToTemplateValue TimeOfDay # 
ToTemplateValue UTCTime # 
ToTemplateValue NominalDiffTime # 
ToTemplateValue Day # 

Associated Types

type TemplateRep Day :: * #

ToTemplateValue UUID # 

Associated Types

type TemplateRep UUID :: * #

ToTemplateValue TemplateString # 
(ToTemplateValue a, (~) * (TemplateRep a) Single) => ToTemplateValue [a] # 

Associated Types

type TemplateRep [a] :: * #

(ToTemplateValue a, (~) * (TemplateRep a) Single) => ToTemplateValue (Maybe a) # 

Associated Types

type TemplateRep (Maybe a) :: * #

(ToTemplateValue a, (~) * (TemplateRep a) Single) => ToTemplateValue (NonEmpty a) # 

Associated Types

type TemplateRep (NonEmpty a) :: * #

ToTemplateValue a => ToTemplateValue (Identity a) # 

Associated Types

type TemplateRep (Identity a) :: * #

(ToTemplateValue a, (~) * (TemplateRep a) Single) => ToTemplateValue (Dual a) # 

Associated Types

type TemplateRep (Dual a) :: * #

(ToTemplateValue a, (~) * (TemplateRep a) Single) => ToTemplateValue (Sum a) # 

Associated Types

type TemplateRep (Sum a) :: * #

(ToTemplateValue a, (~) * (TemplateRep a) Single) => ToTemplateValue (Product a) # 

Associated Types

type TemplateRep (Product a) :: * #

(ToTemplateValue a, (~) * (TemplateRep a) Single) => ToTemplateValue (First a) # 

Associated Types

type TemplateRep (First a) :: * #

(ToTemplateValue a, (~) * (TemplateRep a) Single) => ToTemplateValue (Last a) # 

Associated Types

type TemplateRep (Last a) :: * #

(ToTemplateValue a, (~) * (TemplateRep a) Single) => ToTemplateValue (Vector a) # 

Associated Types

type TemplateRep (Vector a) :: * #

(ToTemplateValue a, ToTemplateValue b, (~) * (TemplateRep a) Single, (~) * (TemplateRep b) Single) => ToTemplateValue (Either a b) # 

Associated Types

type TemplateRep (Either a b) :: * #

(ToTemplateValue a, (~) * (TemplateRep a) Single, ToTemplateValue b, (~) * (TemplateRep b) Single) => ToTemplateValue (a, b) # 

Associated Types

type TemplateRep (a, b) :: * #

Methods

toTemplateValue :: (a, b) -> TemplateValue (TemplateRep (a, b)) #

(ToTemplateValue k, (~) * (TemplateRep k) Single, ToTemplateValue v, (~) * (TemplateRep v) Single) => ToTemplateValue (Map k v) # 

Associated Types

type TemplateRep (Map k v) :: * #

(ToTemplateValue k, (~) * (TemplateRep k) Single, ToTemplateValue v, (~) * (TemplateRep v) Single) => ToTemplateValue (HashMap k v) # 

Associated Types

type TemplateRep (HashMap k v) :: * #

(ToTemplateValue k, (~) * (TemplateRep k) Single, ToTemplateValue v, (~) * (TemplateRep v) Single) => ToTemplateValue (AList k v) # 

Associated Types

type TemplateRep (AList k v) :: * #

(ToTemplateValue a, (~) * (TemplateRep a) Single, ToTemplateValue b, (~) * (TemplateRep b) Single, ToTemplateValue c, (~) * (TemplateRep c) Single) => ToTemplateValue (a, b, c) # 

Associated Types

type TemplateRep (a, b, c) :: * #

Methods

toTemplateValue :: (a, b, c) -> TemplateValue (TemplateRep (a, b, c)) #

(ToTemplateValue a, (~) * (TemplateRep a) Single, ToTemplateValue b, (~) * (TemplateRep b) Single, ToTemplateValue c, (~) * (TemplateRep c) Single, ToTemplateValue d, (~) * (TemplateRep d) Single) => ToTemplateValue (a, b, c, d) # 

Associated Types

type TemplateRep (a, b, c, d) :: * #

Methods

toTemplateValue :: (a, b, c, d) -> TemplateValue (TemplateRep (a, b, c, d)) #

(ToTemplateValue a, (~) * (TemplateRep a) Single, ToTemplateValue b, (~) * (TemplateRep b) Single, ToTemplateValue c, (~) * (TemplateRep c) Single, ToTemplateValue d, (~) * (TemplateRep d) Single, ToTemplateValue e, (~) * (TemplateRep e) Single) => ToTemplateValue (a, b, c, d, e) # 

Associated Types

type TemplateRep (a, b, c, d, e) :: * #

Methods

toTemplateValue :: (a, b, c, d, e) -> TemplateValue (TemplateRep (a, b, c, d, e)) #

(ToTemplateValue a, (~) * (TemplateRep a) Single, ToTemplateValue b, (~) * (TemplateRep b) Single, ToTemplateValue c, (~) * (TemplateRep c) Single, ToTemplateValue d, (~) * (TemplateRep d) Single, ToTemplateValue e, (~) * (TemplateRep e) Single, ToTemplateValue f, (~) * (TemplateRep f) Single) => ToTemplateValue (a, b, c, d, e, f) # 

Associated Types

type TemplateRep (a, b, c, d, e, f) :: * #

Methods

toTemplateValue :: (a, b, c, d, e, f) -> TemplateValue (TemplateRep (a, b, c, d, e, f)) #

(ToTemplateValue a, (~) * (TemplateRep a) Single, ToTemplateValue b, (~) * (TemplateRep b) Single, ToTemplateValue c, (~) * (TemplateRep c) Single, ToTemplateValue d, (~) * (TemplateRep d) Single, ToTemplateValue e, (~) * (TemplateRep e) Single, ToTemplateValue f, (~) * (TemplateRep f) Single, ToTemplateValue g, (~) * (TemplateRep g) Single) => ToTemplateValue (a, b, c, d, e, f, g) # 

Associated Types

type TemplateRep (a, b, c, d, e, f, g) :: * #

Methods

toTemplateValue :: (a, b, c, d, e, f, g) -> TemplateValue (TemplateRep (a, b, c, d, e, f, g)) #

newtype AList k v #

A simple list of key value pairs. Useful when you want to be able to have multiple duplicate keys, which Map and HashMap don't support.

Constructors

AList 

Fields

Instances

(Eq v, Eq k) => Eq (AList k v) # 

Methods

(==) :: AList k v -> AList k v -> Bool #

(/=) :: AList k v -> AList k v -> Bool #

(Read v, Read k) => Read (AList k v) # 
(Show v, Show k) => Show (AList k v) # 

Methods

showsPrec :: Int -> AList k v -> ShowS #

show :: AList k v -> String #

showList :: [AList k v] -> ShowS #

(ToTemplateValue k, (~) * (TemplateRep k) Single, ToTemplateValue v, (~) * (TemplateRep v) Single) => ToTemplateValue (AList k v) # 

Associated Types

type TemplateRep (AList k v) :: * #

type TemplateRep (AList k v) # 

type UriTemplate = [TemplateSegment] #

A URI template is fundamentally a bunch of segments that are either constants or else an interpolation

data TemplateSegment #

Constructors

Literal String

A literal string. No URI escaping will be performed

Embed Modifier [Variable]

An interpolation can have multiple variables (separated by commas in the textual format)

data Modifier #

How an interpolated value should be rendered

Constructors

Simple

No prefix

Reserved

Prefixed by +

Fragment

Prefixed by #

Label

Prefixed by .

PathSegment

Prefixed by /

PathParameter

Prefixed by ;

Query

Prefixed by ?

QueryContinuation

Prefixed by &

data TemplateValue a where #

All values must reduce to a single value pair, an associative list of keys and values, or a list of values without keys.

Implementing a new output format for URI templates

class Monoid (Builder a) => Buildable a where #

Minimal complete definition

build, addChar, addString

Associated Types

type Builder a #

Methods

build :: Builder a -> a #

Convert the intermediate output into the end result

addChar :: Proxy a -> Char -> Builder a #

Construct an appendable character representation

addString :: Proxy a -> String -> Builder a #

Construct an appendable string representation

Instances

Buildable String # 
Buildable ByteString # 
Buildable ByteString # 
Buildable Text # 

Associated Types

type Builder Text :: * #

Buildable Text # 

Associated Types

type Builder Text :: * #

Buildable Builder # 
Buildable Builder #