Skip to content
This repository has been archived by the owner on Apr 24, 2024. It is now read-only.

Commit

Permalink
! can: replace InetSocketAddress in HostConnectorSetup with hostname/…
Browse files Browse the repository at this point in the history
…port pair, fixes #394

Since two `InetSocketAddress` instances are equal if their hostnames resolve to the same IP/port (i.e. the address for "www.spray.io" and "spray.io" compare equal) the HTTP layer wasn't distinguishing properly between them.
This patch fixes this problem.
If you were relying on constructing an `HostConnectorSetup` with an `InetSocketAddress` you need to change your code to provide a host and port explicitly.
  • Loading branch information
sirthias committed Jul 25, 2013
1 parent 99d24be commit a47f3b0
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 15 deletions.
Expand Up @@ -104,6 +104,15 @@ class SprayCanClientSpec extends Specification {
hostConnector1 === hostConnector2
}

"return the different HostConnectors for setup requests with differing hostnames" in new TestSetup {
val probe = TestProbe()
probe.send(IO(Http), Http.HostConnectorSetup("www.spray.io"))
val Http.HostConnectorInfo(hostConnector1, _) = probe.expectMsgType[Http.HostConnectorInfo]
probe.send(IO(Http), Http.HostConnectorSetup("spray.io"))
val Http.HostConnectorInfo(hostConnector2, _) = probe.expectMsgType[Http.HostConnectorInfo]
hostConnector1 !== hostConnector2
}

"properly complete a simple request/response cycle with a Host-header request" in new TestSetup {
val (probe, hostConnector) = sendViaHostConnector(Get("/hij") ~> Host(hostname, port) ~> Date(DateTime.now))
verifyServerSideRequestAndReply(s"http://$hostname:$port/hij", probe)
Expand Down
10 changes: 3 additions & 7 deletions spray-can/src/main/scala/spray/can/Http.scala
Expand Up @@ -53,18 +53,14 @@ object Http extends ExtensionKey[HttpExt] {
apply(listener, new InetSocketAddress(interface, port), backlog, options, settings)
}

case class HostConnectorSetup(remoteAddress: InetSocketAddress,
options: immutable.Traversable[Inet.SocketOption],
settings: Option[HostConnectorSettings])(implicit val sslEngineProvider: ClientSSLEngineProvider) extends Command {
case class HostConnectorSetup(host: String, port: Int = 80,
options: immutable.Traversable[Inet.SocketOption] = Nil,
settings: Option[HostConnectorSettings] = None)(implicit val sslEngineProvider: ClientSSLEngineProvider) extends Command {
private[can] def normalized(implicit refFactory: ActorRefFactory) =
if (settings.isDefined) this
else copy(settings = Some(HostConnectorSettings(actorSystem)))
}
object HostConnectorSetup {
def apply(host: String, port: Int = 80, options: immutable.Traversable[Inet.SocketOption] = Nil,
settings: Option[HostConnectorSettings] = None)(implicit sslEngineProvider: ClientSSLEngineProvider): HostConnectorSetup =
apply(new InetSocketAddress(host, port), options, settings)

def apply(host: String, port: Int, sslEncryption: Boolean)(implicit refFactory: ActorRefFactory, sslEngineProvider: ClientSSLEngineProvider): HostConnectorSetup = {
val connectionSettings = ClientConnectionSettings(actorSystem).copy(sslEncryption = sslEncryption)
apply(host, port, settings = Some(HostConnectorSettings(actorSystem).copy(connectionSettings = connectionSettings)))
Expand Down
Expand Up @@ -16,7 +16,6 @@

package spray.can.client

import java.net.InetSocketAddress
import scala.collection.immutable
import scala.collection.immutable.Queue
import scala.concurrent.duration.Duration
Expand All @@ -28,7 +27,7 @@ import spray.can.Http
import spray.io.ClientSSLEngineProvider
import spray.http._

private[client] class HttpHostConnectionSlot(remoteAddress: InetSocketAddress,
private[client] class HttpHostConnectionSlot(host: String, port: Int,
options: immutable.Traversable[Inet.SocketOption],
idleTimeout: Duration,
clientConnectionSettingsGroup: ActorRef)(implicit sslEngineProvider: ClientSSLEngineProvider)
Expand All @@ -44,8 +43,8 @@ private[client] class HttpHostConnectionSlot(remoteAddress: InetSocketAddress,

{
case ctx: RequestContext
log.debug("Attempting new connection to {}", remoteAddress)
clientConnectionSettingsGroup ! Http.Connect(remoteAddress, None, options, None)
log.debug("Attempting new connection to {}:{}", host, port)
clientConnectionSettingsGroup ! Http.Connect(host, port, None, options, None)
context.setReceiveTimeout(Duration.Undefined)
context.become(connecting(Queue(ctx)))

Expand All @@ -72,7 +71,7 @@ private[client] class HttpHostConnectionSlot(remoteAddress: InetSocketAddress,
context.become(terminating(context.watch(sender)))

case _: Http.Connected
log.debug("Connection to {} established, dispatching {} pending requests", remoteAddress, openRequests.size)
log.debug("Connection to {}:{} established, dispatching {} pending requests", host, port, openRequests.size)
openRequests foreach dispatchToServer(sender)
context.become(connected(context.watch(sender), openRequests))

Expand Down
Expand Up @@ -34,12 +34,12 @@ private[can] class HttpHostConnector(normalizedSetup: Http.HostConnectorSetup, c
private[this] var openRequestCounts = Map.empty[ActorRef, Int] // open requests per child, holds -1 if unconnected
private[this] val hostHeader = {
val encrypted = settings.connectionSettings.sslEncryption
val port = normalizedSetup.remoteAddress.getPort match {
val port = normalizedSetup.port match {
case 443 if encrypted 0
case 80 if !encrypted 0
case x x
}
HttpHeaders.Host(normalizedSetup.remoteAddress.getHostName, port)
HttpHeaders.Host(normalizedSetup.host, port)
}

context.setReceiveTimeout(settings.idleTimeout)
Expand Down Expand Up @@ -122,7 +122,7 @@ private[can] class HttpHostConnector(normalizedSetup: Http.HostConnectorSetup, c
def newConnectionChild(): ActorRef = {
val child = context.watch {
context.actorOf(
props = Props(new HttpHostConnectionSlot(remoteAddress, options, settings.idleTimeout,
props = Props(new HttpHostConnectionSlot(host, port, options, settings.idleTimeout,
clientConnectionSettingsGroup)),
name = counter.next().toString)
}
Expand Down

0 comments on commit a47f3b0

Please sign in to comment.