Parameter Filters

Johannes Rudolph edited this page Aug 14, 2013 · 11 revisions

. . .

Deprecation Note

This documentation is for release 0.9.0 (from 03/2012), which is built against Scala 2.9.1 and Akka 1.3.1 (see Requirements for more information). Most likely, this is not the place you want to look for information. Please turn to the main spray site at for more information about other available versions.

. . .

The parameter/parameters directives filter on the existence of query parameters and extract their values, either as a String or already converted to another type. The parameter directives takes only one argument, the parameters directive several. Every argument is of type ParameterMatcher and normally triggers the extraction of the corresponding query parameters value.

Usually you do not create ParameterMatcher instances yourself but rely on two implicits that automatically convert Strings and Symbols to ParameterMatcher instances, as in this example:

parameters("name", 'firstname) { (name, firstname) =>

When a request to the URI ...?name=smith&firstname=bob comes in, this directive extracts the string values of the respective query parameters and passes the request on to its inner route. If either of the two query parameters is not present in the request it is rejected (and either handled by a subsequent route in the routing structure or not, in the latter of which a 404 Not Found error response is returned, with a respective informational text as the response body).

The behavior of a ParameterMatcher can be further influenced in the following ways:

  1. By appending ? to the matcher you can make the parameter optional. The extracted value will then be of type Option[String].

  2. By giving the ? call an argument you can supply a default value that is used as the extracted value in case the respective query parameter is not present. If the argument is not of type String but something else, this also automatically triggers a type conversion.

  3. By appending the matcher with an as[T] call, you explicitly request a type conversion of the query parameter value.

  4. By appending the matcher with ! and a specific value you turn the ParameterMatcher into a RequiredParameterMatcher, which will only let the request pass if a query parameter with the respective name is present and has a value that corresponds to the one given. (Note that you cannot put a RequiredParameterMatcher and a regular ParameterMatcher in the same directive call!).

spray comes with predefined converters for the following types Int, Long, Double, Float, Short, Byte, Boolean, Symbol. If there is an error during the type conversion the request will be rejected with a MalformedQueryParamRejection, which will, by default, trigger a 400 Bad Request error response with a respective informational text in the body.


Simple, required String parameter:

parameter("name") { name =>
  ... // name is a String

An optional String, a required String and an optional Int parameter with a default value:

parameters("name"?, 'firstname, 'age ? 32) { (name, firstname, age) =>
  ... // name is an Option[String], firstName is a String and age is an Int

A required Double, an optional Long and an optional Boolean parameter with default value:

parameters('[Double], '[Long]?, 'deep ? true) { (factor, key, deep) =>
  ... // factor is a Double, key is an Option[Long] and deep is a Boolean

A required Int, an optional Int and an optional Long parameter with a default value, all given as hex values:

parameters(`mask as(HexInt), `, `flags as(HexLong) ? 0x1F { (mask, more, flags) =>
  ... // mask is an Int, more is an Option[Int] and flags is a Long

Using a required parameter value for method tunneling:

(put | parameter('method ! "put")) {
  ... // responds to PUT requests or other requests
      // where query parameter "method" has value "put" 

Using a path and a parameters directive with Case Class Extraction:

case class Color(name: String, red: Int, green: Int, blue: Int)

val colorPathAndParams = path("color" / "[^/]+".r) &
  parameters('red as[Int], 'green as[Int], 'blue as[Int])

val route = { color =>
   ... // color is an instance of Color

Custom Converters

Creating custom type converters for your own types is no problem at all. All you need to do is to supply an implicit Deserializer for your type. You might want to take the predefined ones as a template. For example, this is the built-in Boolean converter:

implicit val String2BooleanConverter = new Deserializer[String, Boolean] {
  def apply(value: String) = value.toLowerCase match {
    case "true" | "yes" | "on" => Right(true)
    case "false" | "no" | "off" => Right(false)
    case x => Left(MalformedContent("'" + x + "' is not a valid Boolean value"))

Many times you might also want to use automatic Case Class Extraction with the parameters directive.