From a2bcc0fb06568ebe9929750fa0e07235fc64dff8 Mon Sep 17 00:00:00 2001 From: Benjamin Thuillier Date: Fri, 26 Sep 2014 10:51:18 +0200 Subject: [PATCH] +htp #15926 Import HostDirectives from spray --- .../directives/HostDirectivesSpec.scala | 55 +++++++++++++++++ .../directives/PathDirectivesSpec.scala | 2 +- .../scala/akka/http/server/Directives.scala | 4 +- .../server/directives/HostDirectives.scala | 61 +++++++++++++++++++ 4 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 akka-http-tests/src/test/scala/akka/http/server/directives/HostDirectivesSpec.scala create mode 100644 akka-http/src/main/scala/akka/http/server/directives/HostDirectives.scala diff --git a/akka-http-tests/src/test/scala/akka/http/server/directives/HostDirectivesSpec.scala b/akka-http-tests/src/test/scala/akka/http/server/directives/HostDirectivesSpec.scala new file mode 100644 index 0000000000..706a52df7f --- /dev/null +++ b/akka-http-tests/src/test/scala/akka/http/server/directives/HostDirectivesSpec.scala @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.server +package directives + +import akka.http.model.headers.Host +import org.scalatest.FreeSpec + +class HostDirectivesSpec extends FreeSpec with GenericRoutingSpec { + "The 'host' directive" - { + "in its simple String form should" - { + "block requests to unmatched hosts" in { + Get() ~> Host("spray.io") ~> { + host("spray.com") { completeOk } + } ~> check { handled shouldEqual false } + } + + "let requests to matching hosts pass" in { + Get() ~> Host("spray.io") ~> { + host("spray.com", "spray.io") { completeOk } + } ~> check { response shouldEqual Ok } + } + } + + "in its simple RegEx form" - { + "block requests to unmatched hosts" in { + Get() ~> Host("spray.io") ~> { + host("hairspray.*".r) { echoComplete } + } ~> check { handled shouldEqual false } + } + + "let requests to matching hosts pass and extract the full host" in { + Get() ~> Host("spray.io") ~> { + host("spra.*".r) { echoComplete } + } ~> check { responseAs[String] shouldEqual "spray.io" } + } + } + + "in its group RegEx form" - { + "block requests to unmatched hosts" in { + Get() ~> Host("spray.io") ~> { + host("hairspray(.*)".r) { echoComplete } + } ~> check { handled shouldEqual false } + } + + "let requests to matching hosts pass and extract the full host" in { + Get() ~> Host("spray.io") ~> { + host("spra(.*)".r) { echoComplete } + } ~> check { responseAs[String] shouldEqual "y.io" } + } + } + } +} diff --git a/akka-http-tests/src/test/scala/akka/http/server/directives/PathDirectivesSpec.scala b/akka-http-tests/src/test/scala/akka/http/server/directives/PathDirectivesSpec.scala index f472af4fd8..6676384edd 100644 --- a/akka-http-tests/src/test/scala/akka/http/server/directives/PathDirectivesSpec.scala +++ b/akka-http-tests/src/test/scala/akka/http/server/directives/PathDirectivesSpec.scala @@ -235,4 +235,4 @@ class PathDirectivesSpec extends RoutingSpec { case None ⇒ failTest("Example '" + exampleString + "' doesn't contain a test uri") } } -} \ No newline at end of file +} diff --git a/akka-http/src/main/scala/akka/http/server/Directives.scala b/akka-http/src/main/scala/akka/http/server/Directives.scala index dbd4d0a3e2..1017e3fbc4 100644 --- a/akka-http/src/main/scala/akka/http/server/Directives.scala +++ b/akka-http/src/main/scala/akka/http/server/Directives.scala @@ -20,7 +20,7 @@ trait Directives extends RouteConcatenation //with FormFieldDirectives //with FutureDirectives //with HeaderDirectives - //with HostDirectives + with HostDirectives //with MarshallingDirectives with MethodDirectives //with MiscDirectives @@ -32,4 +32,4 @@ trait Directives extends RouteConcatenation //with SchemeDirectives //with SecurityDirectives -object Directives extends Directives \ No newline at end of file +object Directives extends Directives diff --git a/akka-http/src/main/scala/akka/http/server/directives/HostDirectives.scala b/akka-http/src/main/scala/akka/http/server/directives/HostDirectives.scala new file mode 100644 index 0000000000..26c274a7e6 --- /dev/null +++ b/akka-http/src/main/scala/akka/http/server/directives/HostDirectives.scala @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.server +package directives + +import scala.util.matching.Regex +import akka.http.util._ + +trait HostDirectives { + import BasicDirectives._ + import RouteDirectives._ + + /** + * Extracts the hostname part of the Host header value in the request. + */ + def hostName: Directive1[String] = HostDirectives._hostName + + /** + * Rejects all requests with a host name different from the given ones. + */ + def host(hostNames: String*): Directive0 = host(hostNames.contains(_)) + + /** + * Rejects all requests for whose host name the given predicate function returns false. + */ + def host(predicate: String ⇒ Boolean): Directive0 = hostName.require(predicate) + + /** + * Rejects all requests with a host name that doesn't have a prefix matching the given regular expression. + * For all matching requests the prefix string matching the regex is extracted and passed to the inner route. + * If the regex contains a capturing group only the string matched by this group is extracted. + * If the regex contains more than one capturing group an IllegalArgumentException is thrown. + */ + def host(regex: Regex): Directive1[String] = { + def forFunc(regexMatch: String ⇒ Option[String]): Directive1[String] = { + hostName.flatMap { name ⇒ + regexMatch(name) match { + case Some(matched) ⇒ provide(matched) + case None ⇒ reject + } + } + } + + regex.groupCount match { + case 0 ⇒ forFunc(regex.findPrefixOf(_)) + case 1 ⇒ forFunc(regex.findPrefixMatchOf(_).map(_.group(1))) + case _ ⇒ throw new IllegalArgumentException("Path regex '" + regex.pattern.pattern + + "' must not contain more than one capturing group") + } + } + +} + +object HostDirectives extends HostDirectives { + import BasicDirectives._ + + private val _hostName: Directive1[String] = + extract(_.request.uri.authority.host.address) +}