+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`
|
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
|
// http://tools.ietf.org/html/rfc7231#section-7.4.2
|
||||||
object Server extends ModeledCompanion {
|
object Server extends ModeledCompanion {
|
||||||
def apply(products: String): Server = apply(ProductVersion.parseMultiple(products))
|
def apply(products: String): Server = apply(ProductVersion.parseMultiple(products))
|
||||||
|
|
|
||||||
|
|
@ -96,10 +96,10 @@ object HeaderParser {
|
||||||
"link",
|
"link",
|
||||||
"location",
|
"location",
|
||||||
"origin",
|
"origin",
|
||||||
"range",
|
|
||||||
"proxy-authenticate",
|
"proxy-authenticate",
|
||||||
"proxy-authorization",
|
"proxy-authorization",
|
||||||
"range",
|
"range",
|
||||||
|
"referer",
|
||||||
"server",
|
"server",
|
||||||
"set-cookie",
|
"set-cookie",
|
||||||
"transfer-encoding",
|
"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
|
// http://tools.ietf.org/html/rfc7233#section-3.1
|
||||||
def `range` = rule { `byte-ranges-specifier` /*| `other-ranges-specifier` */ ~ EOI ~> (Range(_, _)) }
|
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
|
// http://tools.ietf.org/html/rfc7231#section-7.4.2
|
||||||
def server = rule { products ~> (Server(_)) }
|
def server = rule { products ~> (Server(_)) }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,8 @@ class HttpHeaderParserSpec extends WordSpec with Matchers with BeforeAndAfterAll
|
||||||
| | ┌─o-r-i-g-i-n-:- (origin)
|
| | ┌─o-r-i-g-i-n-:- (origin)
|
||||||
| | | ┌─e-n-t-i-c-a-t-e-:- (proxy-authenticate)
|
| | | ┌─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)
|
| | ┌─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)
|
| └─s-e-r-v-e-r-:- (server)
|
||||||
| | └─t---c-o-o-k-i-e-:- (set-cookie)
|
| | └─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)
|
| | ┌─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)
|
| └─x---f-o-r-w-a-r-d-e-d---f-o-r-:- (x-forwarded-for)
|
||||||
|""" -> parser.formatTrie
|
|""" -> 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
|
parser.contentHistogram shouldEqual
|
||||||
Map("connection" -> 3, "Content-Length" -> 1, "accept" -> 2, "cache-control" -> 2, "expect" -> 1)
|
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) {
|
randomHeaders.take(300).foldLeft(0) {
|
||||||
case (acc, rawHeader) ⇒ acc + parseAndCache(rawHeader.toString + "\r\nx", rawHeader)
|
case (acc, rawHeader) ⇒ acc + parseAndCache(rawHeader.toString + "\r\nx", rawHeader)
|
||||||
} shouldEqual 99 // number of cache hits
|
} shouldEqual 98 // number of cache hits
|
||||||
parser.formatSizes shouldEqual "3040 nodes, 115 branchData rows, 255 values"
|
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() {
|
"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) {
|
randomHostHeaders.take(300).foldLeft(0) {
|
||||||
case (acc, header) ⇒ acc + parseAndCache(header.toString + "\r\nx", header)
|
case (acc, header) ⇒ acc + parseAndCache(header.toString + "\r\nx", header)
|
||||||
} shouldEqual 12 // number of cache hits
|
} 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() {
|
"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""")))
|
`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" in {
|
||||||
"Server: as fghf.fdf/xx" =!= `Server`(Vector(ProductVersion("as"), ProductVersion("fghf.fdf", "xx")))
|
"Server: as fghf.fdf/xx" =!= `Server`(Vector(ProductVersion("as"), ProductVersion("fghf.fdf", "xx")))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue