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

xitrum.Server.scala Maven / Gradle / Ivy

The newest version!
package xitrum

import io.netty.channel.{ChannelInitializer, EventLoopGroup}
import io.netty.channel.socket.SocketChannel
import io.netty.util.ResourceLeakDetector

import xitrum.handler.{Bootstrap, DefaultHttpChannelInitializer, NetOption, SslChannelInitializer}
import xitrum.metrics.MetricsManager

object Server {
  private var eventLoopGroups = Seq.empty[EventLoopGroup]

  /**
   * Starts with the default ChannelInitializer provided by Xitrum.
   */
  def start(): Seq[EventLoopGroup] = {
    start(new DefaultHttpChannelInitializer)
  }

  /**
   * Starts with your custom ChannelInitializer. For an example, see
   * xitrum.handler.DefaultHttpChannelInitializer.
   * SSL codec handler will be automatically prepended for HTTPS server.
   */
  def start(httpChannelInitializer: ChannelInitializer[SocketChannel]): Seq[EventLoopGroup] = {
    Config.xitrum.loadExternalEngines()

    // Trick to start actorRegistry on startup
    xitrum.sockjs.SockJsAction.entropy()

    if (Config.xitrum.metrics.isDefined) MetricsManager.start()

    Config.routes.logAll()

    // By default, ResourceLeakDetector is enabled and at SIMPLE level
    // http://netty.io/4.0/api/io/netty/util/ResourceLeakDetector.Level.html
    if (!Config.productionMode) ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED)

    // Lastly, start the server(s) after necessary things have been prepared
    val portConfig = Config.xitrum.port
    if (portConfig.http.isDefined)  eventLoopGroups = eventLoopGroups ++ doStart(https = false, httpChannelInitializer)
    if (portConfig.https.isDefined) eventLoopGroups = eventLoopGroups ++ doStart(https = true,  httpChannelInitializer)

    // Flash socket server may use same port with HTTP server
    if (portConfig.flashSocketPolicy.isDefined) {
      if (portConfig.flashSocketPolicy != portConfig.http) {
        eventLoopGroups = eventLoopGroups ++ FlashSocketPolicyServer.start()
      } else {
        Log.info("Flash socket policy file will be served by the HTTP server")
      }
    }

    if (Config.productionMode)
      Log.info(s"Xitrum $version started in production mode")
    else
      Log.info(s"Xitrum $version started in development mode")

    // This is a good timing to warn, after Xitrum has just started
    Config.warnOnDefaultSecureKey()

    eventLoopGroups
  }

  /**
   * Stops Xitrum gracefully.
   * Do not call in Ximtrum action thread to avoid deadlock (start a new thread or use [[stopAtShutdown]]).
   */
  def stop(): Unit = {
    Log.info(s"Xitrum $version gracefully stopping...")

    val futures = eventLoopGroups.map(_.shutdownGracefully())
    futures.foreach(_.awaitUninterruptibly())

    Log.info(s"Xitrum $version gracefully stopped")
  }

  /**
   * Registers a JVM shutdown hook that calls [[stop]] to stop Xitrum gracefully.
   * After the hook has been registered, you can stop Xitrum gracefully by running OS command `kill `.
   */
  def stopAtShutdown(): Unit = {
    Runtime.getRuntime.addShutdownHook(new Thread(() => Server.this.stop()))
  }

  //----------------------------------------------------------------------------

  private def doStart(https: Boolean, nonSslChannelInitializer: ChannelInitializer[SocketChannel]): Seq[EventLoopGroup] = {
    val channelInitializer =
      if (https)
        new SslChannelInitializer(nonSslChannelInitializer)
      else
        nonSslChannelInitializer

    val (bootstrap, groups) = Bootstrap.newBootstrap(channelInitializer)

    val portConfig      = Config.xitrum.port
    val (service, port) = if (https) ("HTTPS", portConfig.https.get) else ("HTTP", portConfig.http.get)

    NetOption.bind(service, bootstrap, port, groups)

    Config.xitrum.interface match {
      case None =>
        Log.info(s"$service server started on port $port")

      case Some(hostnameOrIp) =>
        Log.info(s"$service server started on $hostnameOrIp:$port")
    }

    groups
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy