diff --git a/shared/src/main/scala/trail/Route.scala b/shared/src/main/scala/trail/Route.scala index 3bc690c..745311d 100644 --- a/shared/src/main/scala/trail/Route.scala +++ b/shared/src/main/scala/trail/Route.scala @@ -57,7 +57,7 @@ object Route { override def url(value: T): String = arg.codec.encode(value).getOrElse("") override def parseInternal(path: Path): Option[(T, Path)] = { val untilSlash = path.path.takeWhile(_ != '/') - arg.codec.decode(Some(untilSlash)) + arg.codec.decode(if (untilSlash.isEmpty) None else Some(untilSlash)) .map(value => (value, path.copy(path = path.path.drop(untilSlash.length + 1)))) } diff --git a/shared/src/test/scala/trail/RouteParseTests.scala b/shared/src/test/scala/trail/RouteParseTests.scala index ea17d32..c306565 100644 --- a/shared/src/test/scala/trail/RouteParseTests.scala +++ b/shared/src/test/scala/trail/RouteParseTests.scala @@ -38,6 +38,19 @@ class RouteParseTests extends FunSpec with Matchers { assert(parsed === Some((("bob", true), 42))) } + it("Route with optional path element can be parsed") { + val disk = Root / Arg[Option[Long]] + assert(disk.parse("/").contains(None)) + assert(disk.parse("/42").contains(Some(42L))) + } + + it("Route with optional path element can be parsed (2)") { + val disk = Root / "disk" / Arg[Option[Long]] + assert(disk.parse("/disk").contains(None)) + assert(disk.parse("/disk/").contains(None)) + assert(disk.parse("/disk/42").contains(Some(42L))) + } + it("Route can be parsed from string") { val userInfo = Root / "user" / Arg[String] / Arg[Boolean]