All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.atmosphere.play.AtmosphereHttpRequestHandler.scala Maven / Gradle / Ivy

There is a newer version: 3.0.0
Show newest version
package org.atmosphere.play

import java.util.concurrent.CompletableFuture

import com.google.inject.Inject
import play.api.http._
import play.api.inject.Injector
import play.api.mvc.{Handler, RequestHeader}
import play.api.routing.Router
import play.core.j._
import play.api.mvc.BodyParser
import play.mvc.Http.RequestBody


class AtmosphereHttpRequestHandler @Inject()(components: JavaHandlerComponents,
                                             router: Router,
                                             errorHandler: HttpErrorHandler,
                                             configuration: HttpConfiguration,
                                             filters: HttpFilters,
                                             injector: Injector)
  extends JavaCompatibleHttpRequestHandler(router, errorHandler, configuration, filters, components) {

  override def routeRequest(request: RequestHeader) = {
    dispatch(request) match {
      case Some(handler) =>
        Option(handler)
      case None =>
        super.routeRequest(request)
    }
  }

  private def isWsSupported(upgradeHeader: Option[String], connectionHeaders: Seq[String]): Boolean =
    upgradeHeader.map("websocket".equalsIgnoreCase)
      .getOrElse(connectionHeaders.contains("upgrade".equalsIgnoreCase _))

  private def dispatch(requestPath: String,
                       controllerClass: Class[_ <: AtmosphereController],
                       upgradeHeader: Option[String],
                       connectionHeaders: Seq[String]): Option[Handler] = {
    if (!AtmosphereCoordinator.instance.matchPath(requestPath))
      None

    else {
      val controller: AtmosphereController =
        Option(injector.instanceOf(controllerClass)).getOrElse(controllerClass.newInstance)

      // Netty fail to decode headers separated by a ','
      val javaAction =
        if (isWsSupported(upgradeHeader, connectionHeaders))
          JavaWebSocket.ofString(controller.webSocket)
        else
          new JavaAction(components) {
            val annotations = new JavaActionAnnotations(controllerClass, controllerClass.getMethod("http"))
            val parser = javaBodyParserToScala(injector.instanceOf(annotations.parser))

            def invocation = CompletableFuture.completedFuture(controller.http)
          }

      Some(javaAction)
    }
  }

  def javaBodyParserToScala(parser: play.mvc.BodyParser[_]): BodyParser[RequestBody] = BodyParser { request =>
    val accumulator = parser.apply(new play.core.j.RequestHeaderImpl(request)).asScala()
    import play.api.libs.iteratee.Execution.Implicits.trampoline
    accumulator.map { javaEither =>
      if (javaEither.left.isPresent) {
        Left(javaEither.left.get().asScala())
      } else {
        Right(new RequestBody(javaEither.right.get()))
      }
    }
  }

  def dispatch(request: RequestHeader): Option[Handler] =
    dispatch(request, classOf[AtmosphereController])

  def dispatch(request: RequestHeader, controllerClass: Class[_ <: AtmosphereController]): Option[Handler] = {
    val upgradeHeader = request.headers.get("Upgrade")
    val connectionHeaders = Option(request.headers.get("Connection")).map(_.toSeq).getOrElse(Seq.empty)
    dispatch(request.path, controllerClass, upgradeHeader, connectionHeaders)
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy