Usage
Parsing
Parsing an URI Template at compile time can be achieved as follows:
import uritemplate4s._
val template = uritemplate"http://example.com/search{?q,lang}"
When an invalid template is supplied, the error will be shown at compile time.
uritemplate"http://example.com/search{q"
// error: not a valid URI Template, Position 1:28, found ""
// uritemplate"http://example.com/search{q"
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
URI Templates are usually dynamically provided, and so will need to be parsed at runtime like so:
val rawTemplate = "http://example.com/search{?q,lang}"
// rawTemplate: String = http://example.com/search{?q,lang}
val parseResult = UriTemplate.parse(rawTemplate)
// parseResult: Either[ParseFailure, UriTemplate] = Right(ComponentsUriTemplate(List(LiteralComponent(Encoded(http://example.com/search)), Expression(Query,List(Varspec(q,EmptyModifier), Varspec(lang,EmptyModifier))))))
Because parsing a template can fail, the result is an Either
of type Either[ParseFailure, UriTemplate]
.
When parsing fails the result is a Left
containing the error with details of the cause.
UriTemplate.parse("http://example.com/search{q")
// res1: Either[ParseFailure, UriTemplate] = Left(
// value = ParseFailure(index = 27, message = "Position 1:28, found \"\"")
// )
To extract the parsed URI Template from the Either
, pattern matching can be used:
val template: UriTemplate = UriTemplate.parse(rawTemplate) match {
case Left(error) => throw error
case Right(parsedTemplate) => parsedTemplate
}
Or more simply:
val template: UriTemplate = UriTemplate.parse(rawTemplate).toTry.get
Template Expansion
A template can be expanded by supplying tuples representing the name/value pairs to be used in expansion.
template.expand("q" -> "After the Quake", "lang" -> "en")
// res2: ExpandResult = Success(
// value = "http://example.com/search?q=After%20the%20Quake&lang=en"
// )
In the previous example it should be noted that the resultant URI is wrapped in a ExpandResult.Success
.
There are some possible soft failures which can occur during template expansion, meaning an expansion
result could be either a ExpandResult.Success
or a ExpandResult.PartialSuccess
.
To extract the result from either case, the .value
field can be used.
val uri = template.expand("q" -> "After the Quake", "lang" -> "en").value
// uri: String = "http://example.com/search?q=After%20the%20Quake&lang=en"
For examples and details of the features supported in URI Template expansion, refer to RFC 6570 Section 3 as well as the tests included in this project.
List Expansion
List expansion is supported as defined in RFC 6570 Level 4.
val listTemplate = UriTemplate.parse("/search{?list}").toTry.get
val seq = Seq("red", "green", "blue")
listTemplate.expand("list" -> seq).value
// res3: String = "/search?list=red,green,blue"
List and Vectors are also supported.
listTemplate.expand("list" -> seq.toList).value
listTemplate.expand("list" -> seq.toVector).value
Associative Array Expansion
Associative array expansion is supported as defined in RFC 6570 Level 4.
val assocTemplate = UriTemplate.parse("/search{?address*}").toTry.get
val addressMap = Map("city" -> "Manchester", "country" -> "England", "postcode" -> "M2 5DB")
assocTemplate.expand("address" -> addressMap).value
// res6: String = "/search?city=Manchester&country=England&postcode=M2%205DB"