/akka-http-core/src/main/scala/akka/http/scaladsl/ServerBuilder.scala

https://github.com/akka/akka-http · Scala · 156 lines · 64 code · 21 blank · 71 comment · 0 complexity · 5a33e2fbc6eb4484cce05ac05200c6f0 MD5 · raw file

  1. /*
  2. * Copyright (C) 2020 Lightbend Inc. <https://www.lightbend.com>
  3. */
  4. package akka.http.scaladsl
  5. import akka.actor.ClassicActorSystemProvider
  6. import akka.annotation.InternalApi
  7. import akka.event.LoggingAdapter
  8. import akka.http.scaladsl
  9. import akka.http.scaladsl.Http.ServerBinding
  10. import akka.http.scaladsl.model.{ HttpRequest, HttpResponse }
  11. import akka.http.scaladsl.settings.ServerSettings
  12. import akka.http.scaladsl.util.FastFuture
  13. import akka.stream.{ Materializer, SystemMaterializer }
  14. import akka.stream.scaladsl.{ Flow, Source }
  15. import scala.concurrent.Future
  16. /**
  17. * Builder API to create server bindings.
  18. *
  19. * Use [[HttpExt.newServerAt()]] to create a builder, use methods to customize settings,
  20. * and then call one of the bind* methods to bind a server.
  21. */
  22. trait ServerBuilder {
  23. /** Change interface to bind to */
  24. def onInterface(interface: String): ServerBuilder
  25. /** Change port to bind to */
  26. def onPort(port: Int): ServerBuilder
  27. /** Use a custom logger */
  28. def logTo(log: LoggingAdapter): ServerBuilder
  29. /**
  30. * Use custom [[ServerSettings]] for the binding.
  31. */
  32. def withSettings(settings: ServerSettings): ServerBuilder
  33. /**
  34. * Adapt the current configured settings with a function.
  35. */
  36. def adaptSettings(f: ServerSettings => ServerSettings): ServerBuilder
  37. /**
  38. * Enable HTTPS for this binding with the given context.
  39. */
  40. def enableHttps(context: HttpsConnectionContext): ServerBuilder
  41. /**
  42. * Use custom [[Materializer]] for the binding
  43. */
  44. def withMaterializer(materializer: Materializer): ServerBuilder
  45. /**
  46. * Bind a new HTTP server at the given endpoint and use the given asynchronous `handler`
  47. * [[akka.stream.scaladsl.Flow]] for processing all incoming connections.
  48. *
  49. * The number of concurrently accepted connections can be configured by overriding
  50. * the `akka.http.server.max-connections` setting. Please see the documentation in the reference.conf for more
  51. * information about what kind of guarantees to expect.
  52. *
  53. * Supports HTTP/2 on the same port if the akka-http2-support module is on the classpath and http2 support is enabled.
  54. */
  55. def bind(f: HttpRequest => Future[HttpResponse]): Future[ServerBinding]
  56. /**
  57. * Bind a new HTTP server at the given endpoint and uses the given `handler`
  58. * [[akka.stream.scaladsl.Flow]] for processing all incoming connections.
  59. *
  60. * The number of concurrently accepted connections can be configured by overriding
  61. * the `akka.http.server.max-connections` setting. Please see the documentation in the reference.conf for more
  62. * information about what kind of guarantees to expect.
  63. *
  64. * Supports HTTP/2 on the same port if the akka-http2-support module is on the classpath and http2 support is enabled.
  65. */
  66. def bindSync(f: HttpRequest => HttpResponse): Future[ServerBinding]
  67. /**
  68. * Binds a new HTTP server at the given endpoint and uses the given `handler`
  69. * [[akka.stream.scaladsl.Flow]] for processing all incoming connections.
  70. *
  71. * The number of concurrently accepted connections can be configured by overriding
  72. * the `akka.http.server.max-connections` setting. Please see the documentation in the reference.conf for more
  73. * information about what kind of guarantees to expect.
  74. */
  75. def bindFlow(handlerFlow: Flow[HttpRequest, HttpResponse, _]): Future[ServerBinding]
  76. /**
  77. * Creates a [[akka.stream.scaladsl.Source]] of [[akka.http.scaladsl.Http.IncomingConnection]] instances which represents a prospective HTTP server binding
  78. * on the given `endpoint`.
  79. *
  80. * Note that each materialization will create a new binding, so
  81. *
  82. * * if the configured port is 0 the resulting source can be materialized several times. Each materialization will
  83. * then be assigned a new local port by the operating system, which can then be retrieved by the materialized
  84. * [[akka.http.scaladsl.Http.ServerBinding]].
  85. *
  86. * * if the configured port is non-zero subsequent materialization attempts of the produced source will immediately
  87. * fail, unless the first materialization has already been unbound. Unbinding can be triggered via the materialized
  88. * [[akka.http.scaladsl.Http.ServerBinding]].
  89. */
  90. def connectionSource(): Source[Http.IncomingConnection, Future[ServerBinding]]
  91. }
  92. /**
  93. * Internal API
  94. *
  95. * Use [[HttpExt.newServerAt]] to create a new server builder.
  96. */
  97. @InternalApi
  98. private[http] object ServerBuilder {
  99. def apply(interface: String, port: Int, system: ClassicActorSystemProvider): ServerBuilder =
  100. Impl(
  101. interface,
  102. port,
  103. scaladsl.HttpConnectionContext,
  104. system.classicSystem.log,
  105. ServerSettings(system.classicSystem),
  106. system,
  107. SystemMaterializer(system).materializer
  108. )
  109. private case class Impl(
  110. interface: String,
  111. port: Int,
  112. context: ConnectionContext,
  113. log: LoggingAdapter,
  114. settings: ServerSettings,
  115. system: ClassicActorSystemProvider,
  116. materializer: Materializer
  117. ) extends ServerBuilder {
  118. private val http: scaladsl.HttpExt = scaladsl.Http(system)
  119. def onInterface(newInterface: String): ServerBuilder = copy(interface = newInterface)
  120. def onPort(newPort: Int): ServerBuilder = copy(port = newPort)
  121. def logTo(newLog: LoggingAdapter): ServerBuilder = copy(log = newLog)
  122. def withSettings(newSettings: ServerSettings): ServerBuilder = copy(settings = newSettings)
  123. def adaptSettings(f: ServerSettings => ServerSettings): ServerBuilder = copy(settings = f(settings))
  124. def enableHttps(newContext: HttpsConnectionContext): ServerBuilder = copy(context = newContext)
  125. def withMaterializer(newMaterializer: Materializer): ServerBuilder = copy(materializer = newMaterializer)
  126. def connectionSource(): Source[Http.IncomingConnection, Future[ServerBinding]] =
  127. http.bindImpl(interface, port, context, settings, log)
  128. def bindFlow(handlerFlow: Flow[HttpRequest, HttpResponse, _]): Future[ServerBinding] =
  129. http.bindAndHandleImpl(handlerFlow, interface, port, context, settings, log)(materializer)
  130. def bind(handler: HttpRequest => Future[HttpResponse]): Future[ServerBinding] =
  131. http.bindAndHandleAsyncImpl(handler, interface, port, context, settings, parallelism = 0, log)(materializer)
  132. def bindSync(handler: HttpRequest => HttpResponse): Future[ServerBinding] =
  133. bind(req => FastFuture.successful(handler(req)))
  134. }
  135. }