+htc #16887 add Upgrade header parsing/rendering

This commit is contained in:
Johannes Rudolph 2015-02-18 17:26:59 +01:00
parent 2cf1c41eef
commit 4e3c1db4bb
5 changed files with 46 additions and 0 deletions

View file

@ -0,0 +1,15 @@
/*
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.http.model.headers
import akka.http.util.{ Rendering, ValueRenderable }
final case class UpgradeProtocol(name: String, version: Option[String] = None) extends ValueRenderable {
def render[R <: Rendering](r: R): r.type = {
r ~~ name
version.foreach(v r ~~ '/' ~~ v)
r
}
}

View file

@ -55,6 +55,7 @@ final case class Connection(tokens: immutable.Seq[String]) extends ModeledHeader
def renderValue[R <: Rendering](r: R): r.type = r ~~ tokens
def hasClose = has("close")
def hasKeepAlive = has("keep-alive")
def hasUpgrade = has("upgrade")
def append(tokens: immutable.Seq[String]) = Connection(this.tokens ++ tokens)
@tailrec private def has(item: String, ix: Int = 0): Boolean =
if (ix < tokens.length)
@ -711,6 +712,19 @@ final case class `Transfer-Encoding`(encodings: immutable.Seq[TransferEncoding])
def getEncodings: Iterable[japi.TransferEncoding] = encodings.asJava
}
// http://tools.ietf.org/html/rfc7230#section-6.7
object Upgrade extends ModeledCompanion {
implicit val protocolsRenderer = Renderer.defaultSeqRenderer[UpgradeProtocol]
}
final case class Upgrade(protocols: immutable.Seq[UpgradeProtocol]) extends ModeledHeader {
import Upgrade.protocolsRenderer
protected[http] def renderValue[R <: Rendering](r: R): r.type = r ~~ protocols
protected def companion: ModeledCompanion = Upgrade
def hasWebsocket: Boolean = protocols.exists(_.name equalsIgnoreCase "websocket")
}
// http://tools.ietf.org/html/rfc7231#section-5.5.3
object `User-Agent` extends ModeledCompanion {
def apply(products: String): `User-Agent` = apply(ProductVersion.parseMultiple(products))

View file

@ -119,6 +119,7 @@ private[http] object HeaderParser {
"sec-websocket-version",
"set-cookie",
"transfer-encoding",
"upgrade",
"user-agent",
"www-authenticate",
"x-forwarded-for")

View file

@ -187,6 +187,15 @@ private[parser] trait SimpleHeaders { this: Parser with CommonRules with CommonA
`cookie-pair` ~ zeroOrMore(ws(';') ~ `cookie-av`) ~ EOI ~> (`Set-Cookie`(_))
}
// http://tools.ietf.org/html/rfc7230#section-6.7
def upgrade = rule {
oneOrMore(protocol).separatedBy(listSep) ~> (Upgrade(_))
}
def protocol = rule {
token ~ optional(ws("/") ~ token) ~> (UpgradeProtocol(_, _))
}
// http://tools.ietf.org/html/rfc7231#section-5.5.3
def `user-agent` = rule { products ~> (`User-Agent`(_)) }

View file

@ -483,6 +483,13 @@ class HttpHeaderSpec extends FreeSpec with Matchers {
.renderedTo("PLAY_FLASH=; Expires=Sun, 07 Dec 2014 22:48:47 GMT; Path=/; HttpOnly")
}
"Upgrade" in {
"Upgrade: abc, def" =!= Upgrade(Vector(UpgradeProtocol("abc"), UpgradeProtocol("def")))
"Upgrade: abc, def/38.1" =!= Upgrade(Vector(UpgradeProtocol("abc"), UpgradeProtocol("def", Some("38.1"))))
"Upgrade: websocket" =!= Upgrade(Vector(UpgradeProtocol("websocket")))
}
"User-Agent" in {
"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31" =!=
`User-Agent`(ProductVersion("Mozilla", "5.0", "Macintosh; Intel Mac OS X 10_8_3"), ProductVersion("AppleWebKit", "537.31"))