Spray: sanitize query params with shapeless

Overkill imports

  import spray.routing._
  import shapeless._
  import poly._

Define sanity check

def sanitize(x: String): String = 
  (escapeJavascript compose escapeHtmlTags compose ...)(x)

Put polymorphic sanity adder

trait DefaultSanity extends Poly1 {
  implicit def saneDefault[A] = at[A](identity)
}

Override sanity for strings

object Sanity extends DefaultSanity {
  implicit def saneString = at[String](sanitize(_))
  implicit def saneOptString = at[Option[String]](_.map(sanitize))
}

Define query params wrapper classes (2 classes just for fun, could be single class)

case class InsaneParams(
  a: Int,
  b: String,
  c: Option[String]
)

case class SaneParams(
  a: Int,
  b: String,
  c: Option[String]
)

Apply sanity to wrapper class

  def sanitizeParams(x: InsaneParams): SaneParams = {
    val saneTuple = InsaneParams.unapply(x).get.map(Sanity)
    (SaneParams.apply _) tupled saneTuple
  }

Upgrade spray parameters directive with some sanity

  val saneParameters = 
    parameters(('a, 'b, 'c.?)).as(InsaneParams).map(sanitizeParams)

At last, define spray route with params sanity check

   import spray.http.StatusCodes.OK

   val route = 
     get("sanity") {
       saneParameters { params =>
      	   // only sane params allowed here!
      	   complete(OK)
      	 }
     }

Igor Shymko

Igor Shymko
Lives and works in Kiev, Ukraine. Writes scala programs as full time job, enjoys good electronic music, tasty coffee, good mood, loves snowboarding!

Lambda and Kappa Architecture

Understanding lambda & kappa architectures Continue reading

GC roots

Published on February 20, 2019

Hylang

Published on February 01, 2019