parameters
This page explains how to extract multiple query parameter values from the request, or parameters that might or might not be present.
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
The parameters directive filters on the existence of several query parameters and extract their values.
Query parameters can be either extracted as a String or can be converted to another type. The parameter name is supplied as a String. Parameter extraction can be modified to mark a query parameter as required, optional, or repeated, or to filter requests where a parameter has a certain value:
"color"
- extract the value of parameter “color” as
String
- reject if the parameter is missing
"color".optional
- (symbolic notation
"color".?
) - extract the optional value of parameter “color” as
Option[String]
"color".withDefault("red")
- (symbolic notation
"color" ? "red"
) - extract the optional value of parameter “color” as
String
with default value"red"
"color".requiredValue("blue")
- (symbolic notation
"color" ! "blue"
) - require the value of parameter “color” to be
"blue"
and extract nothing - reject if the parameter is missing or has a different value
"amount".as[Int]
- extract the value of parameter “amount” as
Int
, you need a matchingUnmarshaller
in scope for that to work (see also Unmarshalling) - reject if the parameter is missing or can’t be unmarshalled to the given type
"amount".as(unmarshaller)
- extract the value of parameter “amount” with an explicit
Unmarshaller
as described in Unmarshalling - reject if the parameter is missing or can’t be unmarshalled to the given type
"distance".repeated
- extract multiple occurrences of parameter “distance” as
Iterable[String]
"distance".as[Int].repeated
- extract multiple occurrences of parameter “distance” as
Iterable[Int]
, you need a matchingUnmarshaller
in scope for that to work (see also Unmarshalling) "distance".as(unmarshaller).repeated
- extract multiple occurrences of parameter “distance” with an explicit
Unmarshaller
as described in Unmarshalling
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.
If an unmarshaller throws an exception while extracting the value of a parameter, the request will be rejected with a MissingQueryParameterRejection
if the unmarshaller threw an Unmarshaller.NoContentException
or a MalformedQueryParamRejection
in all other cases. (see also Rejections)
There’s also a singular version, parameter. Form fields can be handled in a similar way, see formFields
.
See When to use which parameter directive? to understand when to use which directive.
Examples
Required parameter
- Scala
-
source
val route = parameters("color", "backgroundColor") { (color, backgroundColor) => complete(s"The color is '$color' and the background is '$backgroundColor'") } // tests: Get("/?color=blue&backgroundColor=red") ~> route ~> check { responseAs[String] shouldEqual "The color is 'blue' and the background is 'red'" } Get("/?color=blue") ~> Route.seal(route) ~> check { status shouldEqual StatusCodes.NotFound responseAs[String] shouldEqual "Request is missing required query parameter 'backgroundColor'" }
- Java
Optional parameter
- Scala
-
source
val route = parameters("color", "backgroundColor".optional) { (color, backgroundColor) => val backgroundStr = backgroundColor.getOrElse("<undefined>") complete(s"The color is '$color' and the background is '$backgroundStr'") } // tests: Get("/?color=blue&backgroundColor=red") ~> route ~> check { responseAs[String] shouldEqual "The color is 'blue' and the background is 'red'" } Get("/?color=blue") ~> route ~> check { responseAs[String] shouldEqual "The color is 'blue' and the background is '<undefined>'" }
- Java
Optional parameter with default value
sourceval route =
parameters("color", "backgroundColor".withDefault("white")) { (color, backgroundColor) =>
complete(s"The color is '$color' and the background is '$backgroundColor'")
}
// tests:
Get("/?color=blue&backgroundColor=red") ~> route ~> check {
responseAs[String] shouldEqual "The color is 'blue' and the background is 'red'"
}
Get("/?color=blue") ~> route ~> check {
responseAs[String] shouldEqual "The color is 'blue' and the background is 'white'"
}
Parameter with required value
The requiredValue
decorator makes the route match only if the parameter contains the specified value.
- Scala
-
source
val route = parameters("color", "action".requiredValue("true")) { (color, _) => complete(s"The color is '$color'.") } // tests: Get("/?color=blue&action=true") ~> route ~> check { responseAs[String] shouldEqual "The color is 'blue'." } Get("/?color=blue&action=false") ~> Route.seal(route) ~> check { status shouldEqual StatusCodes.NotFound responseAs[String] shouldEqual "Request is missing required value 'true' for query parameter 'action'" }
- Java
Deserialized parameter
- Scala
-
source
val route = parameters("color", "count".as[Int]) { (color, count) => complete(s"The color is '$color' and you have $count of it.") } // tests: Get("/?color=blue&count=42") ~> route ~> check { responseAs[String] shouldEqual "The color is 'blue' and you have 42 of it." } Get("/?color=blue&count=blub") ~> Route.seal(route) ~> check { status shouldEqual StatusCodes.BadRequest responseAs[String] shouldEqual "The query parameter 'count' was malformed:\n'blub'" + " is not a valid 32-bit signed integer value" }
- Java
Repeated parameter
sourceval route =
parameters("color", "city".repeated) { (color, cities) =>
cities.toList match {
case Nil => complete(s"The color is '$color' and there are no cities.")
case city :: Nil => complete(s"The color is '$color' and the city is $city.")
case multiple => complete(s"The color is '$color' and the cities are ${multiple.mkString(", ")}.")
}
}
// tests:
Get("/?color=blue") ~> route ~> check {
responseAs[String] shouldEqual "The color is 'blue' and there are no cities."
}
Get("/?color=blue&city=Chicago") ~> Route.seal(route) ~> check {
responseAs[String] shouldEqual "The color is 'blue' and the city is Chicago."
}
Get("/?color=blue&city=Chicago&city=Boston") ~> Route.seal(route) ~> check {
responseAs[String] shouldEqual "The color is 'blue' and the cities are Boston, Chicago."
}
CSV parameter
sourceval route =
parameter("names".as(CsvSeq[String])) { names =>
complete(s"The parameters are ${names.mkString(", ")}")
}
// tests:
Get("/?names=") ~> route ~> check {
responseAs[String] shouldEqual "The parameters are "
}
Get("/?names=Caplin") ~> route ~> check {
responseAs[String] shouldEqual "The parameters are Caplin"
}
Get("/?names=Caplin,John") ~> route ~> check {
responseAs[String] shouldEqual "The parameters are Caplin, John"
}
Get("/?names=Caplin,John,") ~> route ~> check {
responseAs[String] shouldEqual "The parameters are Caplin, John, "
}
Repeated, deserialized parameter
sourceval route =
parameters("color", "distance".as[Int].repeated) { (color, distances) =>
distances.toList match {
case Nil => complete(s"The color is '$color' and there are no distances.")
case distance :: Nil => complete(s"The color is '$color' and the distance is $distance.")
case multiple => complete(s"The color is '$color' and the distances are ${multiple.mkString(", ")}.")
}
}
// tests:
Get("/?color=blue") ~> route ~> check {
responseAs[String] shouldEqual "The color is 'blue' and there are no distances."
}
Get("/?color=blue&distance=5") ~> Route.seal(route) ~> check {
responseAs[String] shouldEqual "The color is 'blue' and the distance is 5."
}
Get("/?color=blue&distance=5&distance=14") ~> Route.seal(route) ~> check {
responseAs[String] shouldEqual "The color is 'blue' and the distances are 14, 5."
}