Merge pull request #16207 from spray/w/16084-CustomHeader-model
+htc #16084 introduce CustomHeader superclass for user-defined headers
This commit is contained in:
commit
a7861a5301
6 changed files with 93 additions and 0 deletions
|
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
package akka.http.model.japi.headers;
|
||||||
|
|
||||||
|
public abstract class CustomHeader extends akka.http.model.HttpHeader {
|
||||||
|
public abstract String name();
|
||||||
|
public abstract String value();
|
||||||
|
|
||||||
|
protected abstract boolean suppressRendering();
|
||||||
|
}
|
||||||
|
|
@ -77,6 +77,10 @@ private[http] class HttpRequestRendererFactory(userAgentHeader: Option[headers.`
|
||||||
case x: `Raw-Request-URI` ⇒ // we never render this header
|
case x: `Raw-Request-URI` ⇒ // we never render this header
|
||||||
renderHeaders(tail, hostHeaderSeen, userAgentSeen, transferEncodingSeen)
|
renderHeaders(tail, hostHeaderSeen, userAgentSeen, transferEncodingSeen)
|
||||||
|
|
||||||
|
case x: CustomHeader ⇒
|
||||||
|
if (!x.suppressRendering) render(x)
|
||||||
|
renderHeaders(tail, hostHeaderSeen, userAgentSeen, transferEncodingSeen)
|
||||||
|
|
||||||
case x: RawHeader if (x is "content-type") || (x is "content-length") || (x is "transfer-encoding") ||
|
case x: RawHeader if (x is "content-type") || (x is "content-length") || (x is "transfer-encoding") ||
|
||||||
(x is "host") || (x is "user-agent") ⇒
|
(x is "host") || (x is "user-agent") ⇒
|
||||||
suppressionWarning(log, x, "illegal RawHeader")
|
suppressionWarning(log, x, "illegal RawHeader")
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,10 @@ private[http] class HttpResponseRendererFactory(serverHeader: Option[headers.Ser
|
||||||
render(x)
|
render(x)
|
||||||
renderHeaders(tail, alwaysClose, connHeader, serverHeaderSeen = true, transferEncodingSeen)
|
renderHeaders(tail, alwaysClose, connHeader, serverHeaderSeen = true, transferEncodingSeen)
|
||||||
|
|
||||||
|
case x: CustomHeader ⇒
|
||||||
|
if (!x.suppressRendering) render(x)
|
||||||
|
renderHeaders(tail, alwaysClose, connHeader, serverHeaderSeen, transferEncodingSeen)
|
||||||
|
|
||||||
case x: RawHeader if (x is "content-type") || (x is "content-length") || (x is "transfer-encoding") ||
|
case x: RawHeader if (x is "content-type") || (x is "content-length") || (x is "transfer-encoding") ||
|
||||||
(x is "date") || (x is "server") || (x is "connection") ⇒
|
(x is "date") || (x is "server") || (x is "connection") ⇒
|
||||||
suppressionWarning(log, x, "illegal RawHeader")
|
suppressionWarning(log, x, "illegal RawHeader")
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,17 @@ sealed trait ModeledHeader extends HttpHeader with Serializable {
|
||||||
protected def companion: ModeledCompanion
|
protected def companion: ModeledCompanion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Superclass for user-defined custom headers defined by implementing `name` and `value`.
|
||||||
|
*/
|
||||||
|
abstract class CustomHeader extends japi.headers.CustomHeader {
|
||||||
|
/** Override to return true if this header shouldn't be rendered */
|
||||||
|
def suppressRendering: Boolean = false
|
||||||
|
|
||||||
|
def lowercaseName: String = name.toRootLowerCase
|
||||||
|
def render[R <: Rendering](r: R): r.type = r ~~ name ~~ ':' ~~ ' ' ~~ value
|
||||||
|
}
|
||||||
|
|
||||||
import japi.JavaMapping.Implicits._
|
import japi.JavaMapping.Implicits._
|
||||||
|
|
||||||
// http://tools.ietf.org/html/rfc7230#section-6.1
|
// http://tools.ietf.org/html/rfc7230#section-6.1
|
||||||
|
|
|
||||||
|
|
@ -190,6 +190,35 @@ class RequestRendererSpec extends FreeSpec with Matchers with BeforeAndAfterAll
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
"render a CustomHeader header" - {
|
||||||
|
"if suppressRendering = false" in new TestSetup(None) {
|
||||||
|
case class MyHeader(number: Int) extends CustomHeader {
|
||||||
|
def name: String = "X-My-Header"
|
||||||
|
def value: String = s"No$number"
|
||||||
|
}
|
||||||
|
HttpRequest(GET, "/abc", List(MyHeader(5))) should renderTo {
|
||||||
|
"""GET /abc HTTP/1.1
|
||||||
|
|X-My-Header: No5
|
||||||
|
|Host: test.com:8080
|
||||||
|
|
|
||||||
|
|"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"not if suppressRendering = true" in new TestSetup(None) {
|
||||||
|
case class MyInternalHeader(number: Int) extends CustomHeader {
|
||||||
|
override def suppressRendering: Boolean = true
|
||||||
|
|
||||||
|
def name: String = "X-My-Internal-Header"
|
||||||
|
def value: String = s"No$number"
|
||||||
|
}
|
||||||
|
HttpRequest(GET, "/abc", List(MyInternalHeader(5))) should renderTo {
|
||||||
|
"""GET /abc HTTP/1.1
|
||||||
|
|Host: test.com:8080
|
||||||
|
|
|
||||||
|
|"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
"properly use URI from Raw-Request-URI header if present" - {
|
"properly use URI from Raw-Request-URI header if present" - {
|
||||||
"GET request with Raw-Request-URI" in new TestSetup() {
|
"GET request with Raw-Request-URI" in new TestSetup() {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
package akka.http.engine.rendering
|
package akka.http.engine.rendering
|
||||||
|
|
||||||
|
import akka.http.model.HttpMethods._
|
||||||
import com.typesafe.config.{ Config, ConfigFactory }
|
import com.typesafe.config.{ Config, ConfigFactory }
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
import scala.concurrent.Await
|
import scala.concurrent.Await
|
||||||
|
|
@ -314,6 +315,38 @@ class ResponseRendererSpec extends FreeSpec with Matchers with BeforeAndAfterAll
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"render a CustomHeader header" - {
|
||||||
|
"if suppressRendering = false" in new TestSetup(None) {
|
||||||
|
case class MyHeader(number: Int) extends CustomHeader {
|
||||||
|
def name: String = "X-My-Header"
|
||||||
|
def value: String = s"No$number"
|
||||||
|
}
|
||||||
|
HttpResponse(200, List(MyHeader(5))) should renderTo {
|
||||||
|
"""HTTP/1.1 200 OK
|
||||||
|
|X-My-Header: No5
|
||||||
|
|Date: Thu, 25 Aug 2011 09:10:29 GMT
|
||||||
|
|Content-Length: 0
|
||||||
|
|
|
||||||
|
|"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"not if suppressRendering = true" in new TestSetup(None) {
|
||||||
|
case class MyInternalHeader(number: Int) extends CustomHeader {
|
||||||
|
override def suppressRendering: Boolean = true
|
||||||
|
|
||||||
|
def name: String = "X-My-Internal-Header"
|
||||||
|
def value: String = s"No$number"
|
||||||
|
}
|
||||||
|
HttpResponse(200, List(MyInternalHeader(5))) should renderTo {
|
||||||
|
"""HTTP/1.1 200 OK
|
||||||
|
|Date: Thu, 25 Aug 2011 09:10:29 GMT
|
||||||
|
|Content-Length: 0
|
||||||
|
|
|
||||||
|
|"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
"The 'Connection' header should be rendered correctly" in new TestSetup() {
|
"The 'Connection' header should be rendered correctly" in new TestSetup() {
|
||||||
import org.scalatest.prop.TableDrivenPropertyChecks._
|
import org.scalatest.prop.TableDrivenPropertyChecks._
|
||||||
import HttpProtocols._
|
import HttpProtocols._
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue