Product Engineer, CTO & a Beer Enthusiast
Experiments, thoughts and scripts documented for posterity.
trait VersionDirectives { val extractVersion: Directive[String :: HNil] = extract { ctx => val header = ctx.request.headers.find(_.name == "X-API-Version") header match { case Some(head) => head.value case _ => "1" //default to 1 } } def versioning: Directive[String :: HNil] = extractVersion.flatMap { v => provide(v) } }In the above code there are two keywords, "extract" and "provide". These are part of Sprays BasicDirective. "extract" basically allows you to extract a single value and "provides" allows you to inject a value into the Directive. But wait, we can make this trait even smaller by getting rid of the provide all together to something as follows:
trait VersionDirectives { def versioning: Directive[String :: HNil] = extract { ctx => val header = ctx.request.headers.find(_.name == "X-API-Version") header match { case Some(head) => head.value case _ => "1" //default to 1 } } }Note: there are more than one way to write same operation in scala/spray. bane of my existence!
trait CustomerService extends HttpService with Json4sSupport with VersionDirectives { val customerRoutes = { path("getCustomer" / Segment) { customerId => get { versioning { v => println(v) //do something now that you have extracted the version number . . . .2) url based - http://{uri}/v1/getCustomer
trait CustomerService extends HttpService with Json4sSupport { val Version = PathMatcher("""v([0-9]+)""".r) .flatMap { case vString :: HNil => { try Some(Integer.parseInt(vString) :: HNil) catch { case _: NumberFormatException => Some(1 :: HNil) //default to version 1 } } } val customerRoutes = pathPrefix(Version) { apiVersion => { //. . . . path("getCustomer" / Segment) { customerId => get { complete { apiVersion match { case 1 => { // do something if version 1 } case 2 => ??? //do something if version 2 case _ => { //do something if any other version } } } } } } } }