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
}
}
}
}
}
}
}
}