scalaz.http.request.RequestHeader.scala Maven / Gradle / Ivy
The newest version!
package scalaz
package http
package request
/**
* HTTP request headers.
* RFC 2616 Section 14 Header Field Definitions.
*
* @author Tony Morris
*/
sealed trait RequestHeader {
/**
* A string representation of this request header.
*/
val asString: String
/**
* Returns true
if this header is an entity header,
* false
otherwise.
*/
lazy val isEntity = this match {
case Entity(_) => true
case _ => false
}
/**
* Returns true
if this header is a general header,
* false
otherwise.
*/
lazy val isGeneral = this match {
case General(_) => true
case _ => false
}
/**
* Returns the result of the given function to this header if it is an
* entity header, otherwise returns the given value.
*/
def entity[X](f: EntityHeader => X, x: => X) = this match {
case Entity(h) => f(h)
case _ => x
}
/**
* Returns the result of the given function to this header if it is a
* general header, otherwise returns the given value.
*/
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 {
/**
* Converts the given entity header into a request header.
*/
implicit def entityToRequest(eh: EntityHeader): RequestHeader = scalaz.http.request.Entity(eh)
/**
* Converts the given general header into a request header.
*/
implicit def generalToRequest(gh: GeneralHeader): RequestHeader = scalaz.http.request.General(gh)
/**
* Converts the given string to a request header. If the string is a known request header, then it is used. If not,
* then it if it is a known general header, then it is used. If not then it is an entity header.
*/
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(_))
/**
* Converts the given list of characters to a request header. If the string is a known request header, then it is
* used. If not, then it if it is a known general header, then it is used. If not then it is an entity header.
*/
implicit def ListRequestHeader: (List[Char] => Option[RequestHeader]) = StringRequestHeader _ compose (_.mkString)
}
/**
* HTTP request headers.
* RFC 2616 Section 14 Header Field Definitions.
*/
object RequestHeader extends RequestHeaders {
/**
* For deconstructing request headers into entity headers.
*/
object Entity {
/**
* Matches if the given request header is an entity header.
*/
def unapply(h: RequestHeader) = h match {
case scalaz.http.request.Entity(x) => Some(x)
case _ => None
}
}
/**
* For deconstructing request headers into general headers.
*/
object General {
/**
* Matches if the given request header is a general header.
*/
def unapply(h: RequestHeader) = h match {
case scalaz.http.request.General(x) => Some(x)
case _ => None
}
}
import GeneralHeader.StringGeneralHeader
import EntityHeader.StringEntityHeader
/**
* A list of known headers.
*/
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))
/**
* Converts a list of characters of the form "abc:def" into a potential request header and non-empty value split at
* the colon (:).
*/
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)))
}
}
}