Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add http2 support in JettyBuilder #3333

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion build.sbt
Expand Up @@ -260,7 +260,8 @@ lazy val jetty = libraryProject("jetty")
.settings(
description := "Jetty implementation for http4s servers",
libraryDependencies ++= Seq(
jettyServlet
jettyServlet,
jettyHttp2Server
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This introduces a new dependency that people won't use by default, which is not great, but I don't want to create another Jetty module, and optional dependencies are frustrating. I think this is the least of all evils.

)
)
.dependsOn(servlet % "compile;test->test", theDsl % "test->test")
Expand Down
28 changes: 26 additions & 2 deletions jetty/src/main/scala/org/http4s/server/jetty/JettyBuilder.scala
Expand Up @@ -9,7 +9,13 @@ import java.util
import javax.net.ssl.{SSLContext, SSLParameters}
import javax.servlet.{DispatcherType, Filter}
import javax.servlet.http.HttpServlet
import org.eclipse.jetty.server.{ServerConnector, Server => JServer}
import org.eclipse.jetty.http2.server.HTTP2CServerConnectionFactory
import org.eclipse.jetty.server.{
ServerConnector,
HttpConfiguration,
HttpConnectionFactory,
Server => JServer
}
import org.eclipse.jetty.server.handler.StatisticsHandler
import org.eclipse.jetty.servlet.{FilterHolder, ServletContextHandler, ServletHolder}
import org.eclipse.jetty.util.component.{AbstractLifeCycle, LifeCycle}
Expand All @@ -33,6 +39,7 @@ sealed class JettyBuilder[F[_]] private (
sslConfig: SslConfig,
mounts: Vector[Mount[F]],
private val serviceErrorHandler: ServiceErrorHandler[F],
supportHttp2: Boolean,
banner: immutable.Seq[String]
)(implicit protected val F: ConcurrentEffect[F])
extends ServletContainer[F]
Expand All @@ -51,6 +58,7 @@ sealed class JettyBuilder[F[_]] private (
sslConfig: SslConfig = sslConfig,
mounts: Vector[Mount[F]] = mounts,
serviceErrorHandler: ServiceErrorHandler[F] = serviceErrorHandler,
supportHttp2: Boolean = supportHttp2,
banner: immutable.Seq[String] = banner
): Self =
new JettyBuilder(
Expand All @@ -63,6 +71,7 @@ sealed class JettyBuilder[F[_]] private (
sslConfig,
mounts,
serviceErrorHandler,
supportHttp2,
banner)

@deprecated(
Expand Down Expand Up @@ -161,15 +170,29 @@ sealed class JettyBuilder[F[_]] private (
def withServiceErrorHandler(serviceErrorHandler: ServiceErrorHandler[F]): Self =
copy(serviceErrorHandler = serviceErrorHandler)

/** Enables HTTP/2 connection upgrade over plain text (no TLS).
* See https://webtide.com/introduction-to-http2-in-jetty */
def withHttp2c: Self =
copy(supportHttp2 = true)

def withoutHttp2c: Self =
copy(supportHttp2 = false)

def withBanner(banner: immutable.Seq[String]): Self =
copy(banner = banner)

private def getConnector(jetty: JServer): ServerConnector =
sslConfig.makeSslContextFactory match {
case Some(sslContextFactory) =>
if (supportHttp2) logger.warn("JettyBuilder does not support HTTP/2 with SSL at the moment")
new ServerConnector(jetty, sslContextFactory)
case None =>
case None if !supportHttp2 =>
new ServerConnector(jetty)
case None if supportHttp2 =>
val config = new HttpConfiguration()
val http1 = new HttpConnectionFactory(config)
val http2c = new HTTP2CServerConnectionFactory(config)
new ServerConnector(jetty, http1, http2c)
}

def resource: Resource[F, Server] =
Expand Down Expand Up @@ -243,6 +266,7 @@ object JettyBuilder {
sslConfig = NoSsl,
mounts = Vector.empty,
serviceErrorHandler = DefaultServiceErrorHandler,
supportHttp2 = false,
banner = defaults.Banner
)

Expand Down
1 change: 1 addition & 0 deletions project/Http4sPlugin.scala
Expand Up @@ -233,6 +233,7 @@ object Http4sPlugin extends AutoPlugin {
lazy val jettyRunner = "org.eclipse.jetty" % "jetty-runner" % jettyServer.revision
lazy val jettyServer = "org.eclipse.jetty" % "jetty-server" % "9.4.28.v20200408"
lazy val jettyServlet = "org.eclipse.jetty" % "jetty-servlet" % jettyServer.revision
lazy val jettyHttp2Server = "org.eclipse.jetty.http2" % "http2-server" % jettyServer.revision
lazy val json4sCore = "org.json4s" %% "json4s-core" % "3.6.7"
lazy val json4sJackson = "org.json4s" %% "json4s-jackson" % json4sCore.revision
lazy val json4sNative = "org.json4s" %% "json4s-native" % json4sCore.revision
Expand Down