Routing library for the Scala platform
Version 0.3.0 features several breaking changes. This release also adds support for Scala Native 0.4.0-M2 and Scala.js 1.2.0 while dropping artefacts for Scala Native 0.3.9 and Scala.js 0.6.
The following route functions were renamed:
parse()
→ parseArgs()
parseInternal()
→ parse()
The second major change is that all routes now require exact matches, restoring the behaviour from before v0.2.0. If this is not desired, you can use the new matchers Elems
or Params
in your routes. Please refer to the manual for examples.
Version 0.2.1 fixes various bugs. It also adds support for Scala 2.13.
The API has not changed.
Version 0.2.0 features a number of user-facing changes. Trail now has zero dependencies, supports Scala Native and has better type inference. You can follow the links below to the pull requests for more information.
Previously, route arguments were encoded using HList
s:
url match {
case Routes.index(HNil) => /// ...
case Routes.details(id :: revision :: HNil) => // ...
}
Routes.details.url(1 :: 2 :: HNil)
Starting from v0.2.0, tuples are used instead:
url match {
case Routes.index(()) => // ...
case Routes.details((id, revision)) => // ...
}
Routes.details.url((1, 2))
Define two routes with the same prefix:
val route = Root / "details"
val route2 = Root / "details" / Arg[Int]
Previously, route
would only match the URL /details
, but now it also matches any URL with this prefix, e.g. /details/42
or /details/a/b
.
In your routing table, you will have to make sure that when matching two routes with the same prefix, the longer one has a higher precedence:
url match {
case route2(id)) => // ...
case route(()) => // ...
}
ParamOpt[T]
was dropped in favour of the more generic Param[Option[T]]
. The route:
val route = Root & ParamOpt[Int]("test")
becomes:
val route = Root & Param[Option[Int]]("test")
In v0.2.0, codecs can return optional values which will be skipped when creating the URL. Similarly, you can detect in decode()
if no value was provided for an argument and return a default value.
implicit case object FooArg extends Codec[Foo] {
override def encode(s: Foo): Option[String] = // ...
override def decode(s: Option[String]): Option[Foo]] = // ...
}
Fragment identifiers are frequently used for routing in single-page applications. In Trail routes, you can specify fragments using the $
sign:
val routeFragment = Root $ Fragment[Int]
routeFragment.parse("/#42") // Some(42)
When you use the parse()
or unapply()
methods, you can now provide a trail.Path()
argument as opposed to a string. If you already have a deconstructed URL, this will reduce the parsing overhead:
route.parse(trail.Path("/user/hello", List("show" -> "false")))
Instead of Shapeless HList
s, v0.2.0 uses tuples for encoding types of path elements.
This change resulted in better IDE support and improved type inference. For example, you can construct route arguments with Some(x)
where previously Option(x)
was required:
val route = Root & Param[Option[Int]]("test")
route(Some(42)) // /?test=42
Also, conditional routes are supported. In v0.1, the following route would not have type-checked:
if (isProduction) Root / "api" / "v2.0" else Root
As a consequence of the tuple refactoring, all external dependencies could be dropped which allows us to now fully support Scala Native.
#14, #20, #24, #25, #28