package scalaz
package http
package request
sealed trait RequestHeader {
val asString: String
lazy val isEntity = this match {
case Entity(_) => true
case _ => false
}
lazy val isGeneral = this match {
case General(_) => true
case _ => false
}
def entity[X](f: EntityHeader => X, x: => X) = this match {
case Entity(h) => f(h)
case _ => x
}
def general[X](f: GeneralHeader => X, x: => X) = this match {
case General(h) => f(h)
case _ => x
}
}
final case object Accept extends RequestHeader {
override val asString = toString
}
final case object AcceptCharset extends RequestHeader {
override val asString = "Accept-Charset"
}
final case object AcceptEncoding extends RequestHeader {
override val asString = "Accept-Encoding"
}
final case object AcceptLanguage extends RequestHeader {
override val asString = "Accept-Language"
}
final case object Authorization extends RequestHeader {
override val asString = toString
}
final case object Expect extends RequestHeader {
override val asString = toString
}
final case object From extends RequestHeader {
override val asString = toString
}
final case object Host extends RequestHeader {
override val asString = toString
}
final case object IfMatch extends RequestHeader {
override val asString = "If-Match"
}
final case object IfModifiedSince extends RequestHeader {
override val asString = "If-Modified-Since"
}
final case object IfNoneMatch extends RequestHeader {
override val asString = "If-None-Match"
}
final case object IfRange extends RequestHeader {
override val asString = "If-Range"
}
final case object IfUnmodifiedSince extends RequestHeader {
override val asString = "If-Unmodified-Since"
}
final case object MaxForwards extends RequestHeader {
override val asString = "Max-Forwards"
}
final case object ProxyAuthorization extends RequestHeader {
override val asString = "Proxy-Authorization"
}
final case object Range extends RequestHeader {
override val asString = toString
}
final case object Referer extends RequestHeader {
override val asString = toString
}
final case object TE extends RequestHeader {
override val asString = toString
}
final case object UserAgent extends RequestHeader {
override val asString = "User-Agent"
}
private final case class Entity(eh: EntityHeader) extends RequestHeader {
override val asString = eh.asString
}
private final case class General(gh: GeneralHeader) extends RequestHeader {
override val asString = gh.asString
}
import Character.isWhitespace
import Scalaz._
import Util.Nel._
trait RequestHeaders {
implicit def entityToRequest(eh: EntityHeader): RequestHeader = scalaz.http.request.Entity(eh)
implicit def generalToRequest(gh: GeneralHeader): RequestHeader = scalaz.http.request.General(gh)
implicit def StringRequestHeader(s: String): Option[RequestHeader] =
RequestHeader.headers find {case (n, h) => n.equalsIgnoreCase(s) } map (_._2) orElse
(s: Option[GeneralHeader]) ∘ (scalaz.http.request.General(_)) orElse
(s: Option[EntityHeader]) ∘ (scalaz.http.request.Entity(_))
implicit def ListRequestHeader: (List[Char] => Option[RequestHeader]) = StringRequestHeader _ compose (_.mkString)
}
object RequestHeader extends RequestHeaders {
object Entity {
def unapply(h: RequestHeader) = h match {
case scalaz.http.request.Entity(x) => Some(x)
case _ => None
}
}
object General {
def unapply(h: RequestHeader) = h match {
case scalaz.http.request.General(x) => Some(x)
case _ => None
}
}
import GeneralHeader.StringGeneralHeader
import EntityHeader.StringEntityHeader
val headers = List(("accept", Accept),
("accept-charset", AcceptCharset),
("accept-encoding", AcceptEncoding),
("accept-language", AcceptLanguage),
("authorization", Authorization),
("from", From),
("host", Host),
("if-match", IfMatch),
("if-modified-since", IfModifiedSince),
("if-none-match", IfNoneMatch),
("if-range", IfRange),
("if-unmodified-since", IfUnmodifiedSince),
("max-forwards", MaxForwards),
("proxy-authorization", ProxyAuthorization),
("range", Range),
("referer", Referer),
("te", TE),
("user-agent", UserAgent))
def requestHeaderValue(cs: List[Char]): Option[(RequestHeader, NonEmptyList[Char])] =
cs span (_ != ':') match {
case (n, v) => {
(n: Option[RequestHeader]) ∗ (h =>
(v.dropWhile(x => x == ':' || isWhitespace(x))).toNel map (v => (h, v)))
}
}
}