parameters
The parameters directive filters on the existence of several query parameters and extract their values.
Signature
def parameters(param: <ParamDef[T]>): Directive1[T]
def parameters(params: <ParamDef[T_i]>*): Directive[T_0 :: ... T_i ... :: HNil]
def parameters(params: <ParamDef[T_0]> :: ... <ParamDef[T_i]> ... :: HNil): Directive[T_0 :: ... T_i ... :: HNil]
The signature shown is simplified and written in pseudo-syntax, the real signature uses magnets. [1] The type <ParamDef> doesn’t really exist but consists of the syntactic variants as shown in the description and the examples.
[1] | See The Magnet Pattern for an explanation of magnet-based overloading. |
Description
Query parameters can be either extracted as a String or can be converted to another type. The parameter name can be supplied either as a String or as a Symbol. Parameter extraction can be modified to mark a query parameter as required or optional or to filter requests where a parameter has a certain value:
- "color"
- extract value of parameter “color” as String
- "color".?
- extract optional value of parameter “color” as Option[String]
- "color" ? "red"
- extract optional value of parameter “color” as String with default value "red"
- "color" ! "blue"
- require value of parameter “color” to be "blue" and extract nothing
- "amount".as[Int]
- extract value of parameter “amount” as Int, you need a matching Deserializer in scope for that to work (see also Unmarshalling)
- "amount".as(deserializer)
- extract value of parameter “amount” with an explicit Deserializer
You can use Case Class Extraction to group several extracted values together into a case-class instance.
Requests missing a required parameter or parameter value will be rejected with an appropriate rejection.
There’s also a singular version, parameter. Form fields can be handled in a similar way, see formFields. If you want unified handling for both query parameters and form fields, see anyParams.
Examples
Required parameter
val route =
parameters('color, 'backgroundColor) { (color, backgroundColor) =>
complete(s"The color is '$color' and the background is '$backgroundColor'")
}
Get("/?color=blue&backgroundColor=red") ~> route ~> check {
responseAs[String] === "The color is 'blue' and the background is 'red'"
}
Get("/?color=blue") ~> sealRoute(route) ~> check {
status === StatusCodes.NotFound
responseAs[String] === "Request is missing required query parameter 'backgroundColor'"
}
Optional parameter
val route =
parameters('color, 'backgroundColor.?) { (color, backgroundColor) =>
val backgroundStr = backgroundColor.getOrElse("<undefined>")
complete(s"The color is '$color' and the background is '$backgroundStr'")
}
Get("/?color=blue&backgroundColor=red") ~> route ~> check {
responseAs[String] === "The color is 'blue' and the background is 'red'"
}
Get("/?color=blue") ~> route ~> check {
responseAs[String] === "The color is 'blue' and the background is '<undefined>'"
}
val route =
parameters('color, 'backgroundColor ? "white") { (color, backgroundColor) =>
complete(s"The color is '$color' and the background is '$backgroundColor'")
}
Get("/?color=blue&backgroundColor=red") ~> route ~> check {
responseAs[String] === "The color is 'blue' and the background is 'red'"
}
Get("/?color=blue") ~> route ~> check {
responseAs[String] === "The color is 'blue' and the background is 'white'"
}
Optional parameter with default value
val route =
parameters('color, 'backgroundColor ? "white") { (color, backgroundColor) =>
complete(s"The color is '$color' and the background is '$backgroundColor'")
}
Get("/?color=blue&backgroundColor=red") ~> route ~> check {
responseAs[String] === "The color is 'blue' and the background is 'red'"
}
Get("/?color=blue") ~> route ~> check {
responseAs[String] === "The color is 'blue' and the background is 'white'"
}
Parameter with required value
val route =
parameters('color, 'action ! "true") { (color) =>
complete(s"The color is '$color'.")
}
Get("/?color=blue&action=true") ~> route ~> check {
responseAs[String] === "The color is 'blue'."
}
Get("/?color=blue&action=false") ~> sealRoute(route) ~> check {
status === StatusCodes.NotFound
responseAs[String] === "The requested resource could not be found."
}
Deserialized parameter
val route =
parameters('color, 'count.as[Int]) { (color, count) =>
complete(s"The color is '$color' and you have $count of it.")
}
Get("/?color=blue&count=42") ~> route ~> check {
responseAs[String] === "The color is 'blue' and you have 42 of it."
}
Get("/?color=blue&count=blub") ~> sealRoute(route) ~> check {
status === StatusCodes.BadRequest
responseAs[String] === "The query parameter 'count' was malformed:\n'blub' is not a valid 32-bit integer value"
}