diff --git a/akka-http-core/src/main/scala/akka/http/model/headers/headers.scala b/akka-http-core/src/main/scala/akka/http/model/headers/headers.scala index 3c51b4545d..383489bf44 100644 --- a/akka-http-core/src/main/scala/akka/http/model/headers/headers.scala +++ b/akka-http-core/src/main/scala/akka/http/model/headers/headers.scala @@ -229,8 +229,21 @@ final case class `Access-Control-Allow-Methods`(methods: immutable.Seq[HttpMetho } // http://www.w3.org/TR/cors/#access-control-allow-origin-response-header -object `Access-Control-Allow-Origin` extends ModeledCompanion -final case class `Access-Control-Allow-Origin`(range: HttpOriginRange) extends japi.headers.AccessControlAllowOrigin with ModeledHeader { +object `Access-Control-Allow-Origin` extends ModeledCompanion { + val `*` = forRange(HttpOriginRange.`*`) + val `null` = forRange(HttpOriginRange()) + def apply(origin: HttpOrigin) = forRange(HttpOriginRange(origin)) + + /** + * Creates an `Access-Control-Allow-Origin` header for the given origin range. + * + * CAUTION: Even though allowed by the spec (http://www.w3.org/TR/cors/#access-control-allow-origin-response-header) + * `Access-Control-Allow-Origin` headers with more than a single origin appear to be largely unsupported in the field. + * Make sure to thoroughly test such usages with all expected clients! + */ + def forRange(range: HttpOriginRange) = new `Access-Control-Allow-Origin`(range) +} +final case class `Access-Control-Allow-Origin` private (range: HttpOriginRange) extends japi.headers.AccessControlAllowOrigin with ModeledHeader { def renderValue[R <: Rendering](r: R): r.type = r ~~ range protected def companion = `Access-Control-Allow-Origin` } diff --git a/akka-http-core/src/main/scala/akka/http/model/parser/SimpleHeaders.scala b/akka-http-core/src/main/scala/akka/http/model/parser/SimpleHeaders.scala index 67fc467c44..f7af9acefe 100644 --- a/akka-http-core/src/main/scala/akka/http/model/parser/SimpleHeaders.scala +++ b/akka-http-core/src/main/scala/akka/http/model/parser/SimpleHeaders.scala @@ -36,10 +36,9 @@ private[parser] trait SimpleHeaders { this: Parser with CommonRules with CommonA } // http://www.w3.org/TR/cors/#access-control-allow-origin-response-header - def `access-control-allow-origin` = rule { - (ws('*') ~ push(HttpOriginRange.`*`) | `origin-list-or-null` ~> (HttpOriginRange(_: _*))) ~ EOI ~> - (`Access-Control-Allow-Origin`(_)) - } + def `access-control-allow-origin` = rule( + ws('*') ~ push(`Access-Control-Allow-Origin`.`*`) + | `origin-list-or-null` ~ EOI ~> (origins ⇒ `Access-Control-Allow-Origin`.forRange(HttpOriginRange(origins: _*)))) // http://www.w3.org/TR/cors/#access-control-expose-headers-response-header def `access-control-expose-headers` = rule { diff --git a/akka-http-core/src/test/scala/akka/http/model/parser/HttpHeaderSpec.scala b/akka-http-core/src/test/scala/akka/http/model/parser/HttpHeaderSpec.scala index 7191378df8..aa4a3e674a 100644 --- a/akka-http-core/src/test/scala/akka/http/model/parser/HttpHeaderSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/model/parser/HttpHeaderSpec.scala @@ -67,11 +67,11 @@ class HttpHeaderSpec extends FreeSpec with Matchers { } "Access-Control-Allow-Origin" in { - "Access-Control-Allow-Origin: *" =!= `Access-Control-Allow-Origin`(HttpOriginRange.`*`) - "Access-Control-Allow-Origin: null" =!= `Access-Control-Allow-Origin`(HttpOriginRange()) - "Access-Control-Allow-Origin: http://spray.io" =!= `Access-Control-Allow-Origin`(HttpOriginRange("http://spray.io")) + "Access-Control-Allow-Origin: *" =!= `Access-Control-Allow-Origin`.`*` + "Access-Control-Allow-Origin: null" =!= `Access-Control-Allow-Origin`.`null` + "Access-Control-Allow-Origin: http://spray.io" =!= `Access-Control-Allow-Origin`("http://spray.io") "Access-Control-Allow-Origin: http://akka.io http://spray.io" =!= - `Access-Control-Allow-Origin`(HttpOriginRange("http://akka.io", "http://spray.io")) + `Access-Control-Allow-Origin`.forRange(HttpOriginRange("http://akka.io", "http://spray.io")) } "Access-Control-Expose-Headers" in {