+hco #16822 add model for Referer header
This commit is contained in:
parent
bffdb998b6
commit
d6bc3ec4c5
6 changed files with 53 additions and 6 deletions
|
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
|
||||
package akka.http.model.japi.headers;
|
||||
|
||||
import akka.http.model.japi.Uri;
|
||||
|
||||
/**
|
||||
* Model for the `Referer` header.
|
||||
* Specification: http://tools.ietf.org/html/rfc7231#section-5.5.2
|
||||
*/
|
||||
public abstract class Referer extends akka.http.model.HttpHeader {
|
||||
public abstract Uri getUri();
|
||||
|
||||
public static Referer create(Uri uri) {
|
||||
return new akka.http.model.headers.Referer(akka.http.model.japi.Util.convertUriToScala(uri));
|
||||
}
|
||||
}
|
||||
|
|
@ -537,6 +537,19 @@ final case class `Remote-Address`(address: RemoteAddress) extends japi.headers.R
|
|||
protected def companion = `Remote-Address`
|
||||
}
|
||||
|
||||
// http://tools.ietf.org/html/rfc7231#section-5.5.2
|
||||
object Referer extends ModeledCompanion
|
||||
final case class Referer(uri: Uri) extends japi.headers.Referer with ModeledHeader {
|
||||
require(uri.fragment == None, "Referer header URI must not contain a fragment")
|
||||
require(uri.authority.userinfo.isEmpty, "Referer header URI must not contain a userinfo component")
|
||||
|
||||
def renderValue[R <: Rendering](r: R): r.type = { import UriRendering.UriRenderer; r ~~ uri }
|
||||
protected def companion = Referer
|
||||
|
||||
/** Java API */
|
||||
def getUri: akka.http.model.japi.Uri = uri.asJava
|
||||
}
|
||||
|
||||
// http://tools.ietf.org/html/rfc7231#section-7.4.2
|
||||
object Server extends ModeledCompanion {
|
||||
def apply(products: String): Server = apply(ProductVersion.parseMultiple(products))
|
||||
|
|
|
|||
|
|
@ -96,10 +96,10 @@ object HeaderParser {
|
|||
"link",
|
||||
"location",
|
||||
"origin",
|
||||
"range",
|
||||
"proxy-authenticate",
|
||||
"proxy-authorization",
|
||||
"range",
|
||||
"referer",
|
||||
"server",
|
||||
"set-cookie",
|
||||
"transfer-encoding",
|
||||
|
|
|
|||
|
|
@ -168,6 +168,13 @@ private[parser] trait SimpleHeaders { this: Parser with CommonRules with CommonA
|
|||
// http://tools.ietf.org/html/rfc7233#section-3.1
|
||||
def `range` = rule { `byte-ranges-specifier` /*| `other-ranges-specifier` */ ~ EOI ~> (Range(_, _)) }
|
||||
|
||||
// http://tools.ietf.org/html/rfc7231#section-5.5.2
|
||||
def referer = rule {
|
||||
// we are bit more relaxed than the spec here by also parsing a potential fragment
|
||||
// but catch it in the `Referer` instance validation (with a `require` in the constructor)
|
||||
runSubParser(new UriParser(_).`URI-reference-pushed`) ~ EOI ~> (Referer(_))
|
||||
}
|
||||
|
||||
// http://tools.ietf.org/html/rfc7231#section-7.4.2
|
||||
def server = rule { products ~> (Server(_)) }
|
||||
|
||||
|
|
|
|||
|
|
@ -153,7 +153,8 @@ class HttpHeaderParserSpec extends WordSpec with Matchers with BeforeAndAfterAll
|
|||
| | ┌─o-r-i-g-i-n-:- (origin)
|
||||
| | | ┌─e-n-t-i-c-a-t-e-:- (proxy-authenticate)
|
||||
| | ┌─p-r-o-x-y---a-u-t-h-o-r-i-z-a-t-i-o-n-:- (proxy-authorization)
|
||||
| | | └─r-a-n-g-e-:- (range)
|
||||
| | | | ┌─a-n-g-e-:- (range)
|
||||
| | | └─r-e-f-e-r-e-r-:- (referer)
|
||||
| └─s-e-r-v-e-r-:- (server)
|
||||
| | └─t---c-o-o-k-i-e-:- (set-cookie)
|
||||
| | ┌─t-r-a-n-s-f-e-r---e-n-c-o-d-i-n-g-:- (transfer-encoding)
|
||||
|
|
@ -162,7 +163,7 @@ class HttpHeaderParserSpec extends WordSpec with Matchers with BeforeAndAfterAll
|
|||
| └─x---f-o-r-w-a-r-d-e-d---f-o-r-:- (x-forwarded-for)
|
||||
|""" -> parser.formatTrie
|
||||
}
|
||||
parser.formatSizes shouldEqual "602 nodes, 42 branchData rows, 57 values"
|
||||
parser.formatSizes shouldEqual "610 nodes, 43 branchData rows, 58 values"
|
||||
parser.contentHistogram shouldEqual
|
||||
Map("connection" -> 3, "Content-Length" -> 1, "accept" -> 2, "cache-control" -> 2, "expect" -> 1)
|
||||
}
|
||||
|
|
@ -234,8 +235,8 @@ class HttpHeaderParserSpec extends WordSpec with Matchers with BeforeAndAfterAll
|
|||
}
|
||||
randomHeaders.take(300).foldLeft(0) {
|
||||
case (acc, rawHeader) ⇒ acc + parseAndCache(rawHeader.toString + "\r\nx", rawHeader)
|
||||
} shouldEqual 99 // number of cache hits
|
||||
parser.formatSizes shouldEqual "3040 nodes, 115 branchData rows, 255 values"
|
||||
} shouldEqual 98 // number of cache hits
|
||||
parser.formatSizes shouldEqual "3036 nodes, 115 branchData rows, 255 values"
|
||||
}
|
||||
|
||||
"continue parsing modelled headers even if the overall cache capacity is reached" in new TestSetup() {
|
||||
|
|
@ -247,7 +248,7 @@ class HttpHeaderParserSpec extends WordSpec with Matchers with BeforeAndAfterAll
|
|||
randomHostHeaders.take(300).foldLeft(0) {
|
||||
case (acc, header) ⇒ acc + parseAndCache(header.toString + "\r\nx", header)
|
||||
} shouldEqual 12 // number of cache hits
|
||||
parser.formatSizes shouldEqual "766 nodes, 51 branchData rows, 69 values"
|
||||
parser.formatSizes shouldEqual "774 nodes, 52 branchData rows, 70 values"
|
||||
}
|
||||
|
||||
"continue parsing raw headers even if the header-specific cache capacity is reached" in new TestSetup() {
|
||||
|
|
|
|||
|
|
@ -339,6 +339,13 @@ class HttpHeaderSpec extends FreeSpec with Matchers {
|
|||
`Proxy-Authorization`(GenericHttpCredentials("Fancy", Map("yes" -> "no", "nonce" -> """4\2""")))
|
||||
}
|
||||
|
||||
"Referer" in {
|
||||
"Referer: https://spray.io/secure" =!= Referer(Uri("https://spray.io/secure"))
|
||||
"Referer: /en-us/default.aspx?foo=bar" =!= Referer(Uri("/en-us/default.aspx?foo=bar"))
|
||||
"Referer: https://akka.io/#sec" =!= ErrorInfo("Illegal HTTP header 'Referer': requirement failed",
|
||||
"Referer header URI must not contain a fragment")
|
||||
}
|
||||
|
||||
"Server" in {
|
||||
"Server: as fghf.fdf/xx" =!= `Server`(Vector(ProductVersion("as"), ProductVersion("fghf.fdf", "xx")))
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue