Frage

To ensure people don't append random query parameters (e.g. appending &r=234522.123 or similar) to avoid hitting our cache I want to have a way to reject any queries that are not handled explicitly. I can of course create one that contains a whitelist, but that would have to be separately maintained and I hate maintaining two things that needs to stay in synch. (Though, it would aid in failing faster.) Is this possible with Spray routing?

War es hilfreich?

Lösung

I ended up with this:

// This contains a white-list of allowed query parameters. This is useful to
// ensure people don't try to use &r=234234 to bust your caches.
def allowedParameters(params: String*): Directive0 = parameterSeq.flatMap {
  case xs =>
    val illegal = xs.collect {
      case (k, _) if !params.contains(k) => k
    }
    if (illegal.nonEmpty)
      reject(ValidationRejection("Illegal query parameters: " + illegal.mkString("", ", ", "\nAllowed ones are: ") + params.mkString(", ")))
    else
      pass
}

For usage, have a look at the unit tests:

val allowedRoute = {
  allowedParameters("foo", "bar") {
    complete("OK")
  }
}

"Allowed Parameter Directive" should "reject parameters not in its whitelist" in {
  Get("/?foo&bar&quux") ~> allowedRoute ~> check {
    handled should equal(false)
    rejection should be(ValidationRejection("Illegal query parameters: quux\nAllowed ones are: foo, bar"))
  }
}

it should "allow properly sorted parameters through" in {
  Get("/?bar&foo") ~> allowedRoute ~> check {
    handled should equal(true)
    responseAs[String] should equal("OK")
  }
}

Andere Tipps

Actually, you have a good solution, i can only suggest a small refactoring:

def only(params: String*): Directive0 = {
  def check: Map[String, String] => Boolean = _.keySet diff params.toSet isEmpty
  parameterMap.require(check, rejection)
}

You can write it as a one-liner, but it would be just longer

With a route like this:

val myRoute = {
  ...
  pathPrefix("test") {
    parameter("good") {
      good =>
        complete("GOOD")
    }
  } ~
 ...
}

Spray will require first parameter to be good and to have value, i.e. ?good=value. No other parameters that have values are allowed.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top