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"