SprayWebSockets icon indicating copy to clipboard operation
SprayWebSockets copied to clipboard

WebSockets makes it impossible to track a client's IP address

Open pmlt opened this issue 11 years ago • 0 comments

A WebSockets server actor listens to certain events related to the connection. Akka's TCP-based IO extension allows us to retrieve the client IP address via the Tcp.Connected event. The sender of this event is supposed to represent the client connection itself.

When using SprayWebSockets, the actor which sends this event no longer represents the client connection. Instead, there is another event which comes later, Sockets.Upgraded, whose sender represents the client connection. The problem is that at this point, there is no way to retrieve the client IP address.

It's easy to verify this behavior with the following program:

import akka.actor._
import akka.io.Tcp, Tcp._
import spray.http.HttpRequest
import spray.can.server.websockets.Sockets
import spray.can.Http

object Simple extends App {

  implicit val system = ActorSystem()

  val act = system.actorOf(Props[Server])
  akka.io.IO(Sockets) ! Http.Bind(act, interface = "localhost", port = 8080)

  class Server extends Actor with ActorLogging {
    def receive = {
      case x: Connected =>
        log.info("Connected: {}", sender)
        sender ! Register(self)
      case x: ConnectionClosed =>
        log.info("Disconnected: {}", sender)
      case Sockets.Upgraded =>
        log.info("Upgraded: {}", sender)
      case req: HttpRequest =>
        sender ! Sockets.UpgradeServer(
          Sockets.acceptAllFunction(req), self)
      case x =>
        log.info("Received data from {}: {}", sender, x.toString)
    }
  }
}

In this example, the actor which sends Tcp.Connected is not the same actor which sends all other events. It should be the same actor...

pmlt avatar Feb 13 '14 22:02 pmlt