如何在编写Spray指令时获得第一个HList(Shapeless,Scala)

时间:2016-04-06 20:08:51

标签: spray shapeless

假设我想创建一个简单的指令,用于从HTTP请求中获取会话标识符,但有一个扭曲:请求可能使用旧格式,但由于向后兼容性,这两者应该被认为是有效的。 / p>

我勾勒出一些简单的东西,它基本上组成了两个现有的指令,结果指令是......

Directive[Option[String] :: Option[String] :: HNil]

这是我的问题的主要内容:是否有任何简洁的方法基本上说“给定一个指令是多个选项的HList,获得第一个并使用否则使用默认值”?

我目前的实施。有效,但看起来有点混乱,根本无法重复使用。

def sessionIdentifier: Directive1[String] = {
  (optionalHeaderValueByName("New-Session-Header") & parameter("oldsessionparam"?)).hmap {
    case Some(x) :: _ :: HNil if x.nonEmpty => x
    case _ :: Some(x) :: HNil if x.nonEmpty => x
    case _ => getNewSessionId()
  }
}

2 个答案:

答案 0 :(得分:1)

如果保证所有元素类型都是Option[String]类型,那么以下内容将是一个小问题,

@ import shapeless._
import shapeless._

@ val opts = Option.empty[String] :: Option("foo") :: Option("bar") :: HNil
opts: Option[String] :: Option[String] :: Option[String] :: HNil = ...

@ opts.toList.flatten.headOption.getOrElse("default")
res0: String = "foo"

答案 1 :(得分:0)

实际上你的实现非常好。它可能被重构为

val sessionParameters =
  optionalHeaderValueByName("New-Session-Header") & parameter("oldsessionparam".?)

val sessionIdentifier =
  sessionParameters.hmap {
    case newId :: oldId :: HNil =>
      newId.filter(_.nonEmpty)
        .orElse(oldId.filter(_.nonEmpty))
        .getOrElse(getNewSessionId())
  }