-
Notifications
You must be signed in to change notification settings - Fork 65
Route Creation
The RhoService
is the primary method for creating routes. Route creation is performed in the constructor using combinators defined in the rho package object.
/// src_inlined SimplePath core/src/test/scala/ApiExamples.scala
new RhoService {
GET / "hello" |>> { () => Ok("Hello, world!") }
}
/// end_src_inlined
The rho DSL defines helpers for creating path, query, and header rules which will match and/or extract data from the Request
. All of these rules can be stored and used in the creation of more complex routes:
/// src_inlined ReusePath core/src/test/scala/ApiExamples.scala
new RhoService {
// A path can be built up in multiple steps and the parts reused
val pathPart1 = GET / "hello"
pathPart1 / "world" |>> { () => Ok("Hello, world!") }
pathPart1 / "you" |>> { () => Ok("Hello, you!") }
}
/// end_src_inlined
Path rules are concerned with defining the path portion of the route. Portions of the path can be matched or captured:
/// src_inlined PathCapture core/src/test/scala/ApiExamples.scala
new RhoService {
// Use combinators to parse and capture path parameters
GET / "helloworldnumber" / pathVar[Int] / "foo" |>> { i: Int => Ok("Received $i") }
// the symbol 'world just says 'capture a String' with variable name "world"
GET / "helloworldstring" / 'world / "foo" |>> { i: String => Ok("Received $i") }
}
/// end_src_inlined
The entire rest of the path can be captured using the *
rule:
/// src_inlined CaptureTail core/src/test/scala/ApiExamples.scala
new RhoService {
// You can capture the entire rest of the tail using *
GET / "hello" / * |>> { r: List[String] => Ok(s"Got the rest: ${r.mkString}") }
}
/// end_src_inlined
Query rules are captured in essentially the same manner as path rules:
/// src_inlined QueryCapture core/src/test/scala/ApiExamples.scala
new RhoService {
// Query parameters can be captured in a similar manner as path fragments
GET / "hello" +? param[Int]("fav") |>> { i: Int => Ok(s"Query 'fav' had Int value $i") }
}
/// end_src_inlined
Of course you can use query capture rules with path capture rules:
/// src_inlined MultiCapture core/src/test/scala/ApiExamples.scala
new RhoService {
// A Path can be made all at once
POST / "hello" / pathVar[Int] +? param[Int]("fav") |>> { (i1: Int, i2: Int) =>
Ok(s"Sum of the number is ${i1 + i2}")
}
}
/// end_src_inlined
Headers work essentially the same as path and query rules:
/// src_inlined HeaderCapture core/src/test/scala/ApiExamples.scala
new RhoService {
GET / "hello" >>> capture(ETag) |>> { tag: ETag =>
Ok(s"Thanks for the tag: $tag")
}
}
/// end_src_inlined
Status codes are not necessarily required: rho will accept anything with an EntityEncoder
:
/// src_inlined ResultTypes core/src/test/scala/ApiExamples.scala
new RhoService {
// Status codes are not mandatory: anything with an `EntityEncoder` will work.
GET / "nostatus" |>> { () => "No status!" }
GET / "taskNoStatus" |>> { () => Task("A Future status!") }
/* Results need not be functions: they can be anything that has
an `EntityEncoder` instance in scope */
GET / "nostatus2" |>> "This is a constant result!"
GET / "taskNoStatus2" |>> Task("This task will be evaluated each time!")
/* We can use a standard http4s.Response, but we don't get any metadata
with it. Useful for things like Websocket support. */
GET / "websockets" |>> { () =>
val exchange: scalaz.stream.Exchange[WebSocketFrame,WebSocketFrame] = ???
WS(exchange)
}
}
/// end_src_inlined
Rho stores as much metadata as it can, including status codes and the response types that accompany them which is very useful for middleware that can take advantage of that information (such as Swagger generation). In order to capture that data use the status code helpers:
/// src_inlined StatusCodes core/src/test/scala/ApiExamples.scala
new RhoService {
GET / "twoResults" |>> { () =>
if (true) Ok("bytes result".getBytes())
else NotFound("Boo... Not found...")
}
}
/// end_src_inlined
For requests that contain a body rho can extract and decode it using the ^
operator with http4s EntityDecoder[A]
's:
/// src_inlined Decoders core/src/test/scala/ApiExamples.scala
/// end_src_inlined