diff options
author | Bjørn Christian Seime <bjorncs@yahooinc.com> | 2022-10-07 14:54:01 +0200 |
---|---|---|
committer | Bjørn Christian Seime <bjorncs@yahooinc.com> | 2022-10-07 15:22:00 +0200 |
commit | ea880e5a8b25e10b3b72e1a4068a92d54d986ca5 (patch) | |
tree | eafcf897e5514e9bee051a968a1572004f66a18a /container-core | |
parent | 43634441529d078fb8c7156356e7d96d299694a4 (diff) |
Create separate Jetty handler chain for each connector
Use connector name and virtual hosts configuration to route requests between handler chains.
Diffstat (limited to 'container-core')
3 files changed, 77 insertions, 44 deletions
diff --git a/container-core/abi-spec.json b/container-core/abi-spec.json index bbee5ffd7da..d324656abf2 100644 --- a/container-core/abi-spec.json +++ b/container-core/abi-spec.json @@ -1202,9 +1202,13 @@ "public void <init>()", "public void <init>(com.yahoo.jdisc.http.ConnectorConfig$ServerName)", "public com.yahoo.jdisc.http.ConnectorConfig$ServerName$Builder fallback(java.lang.String)", + "public com.yahoo.jdisc.http.ConnectorConfig$ServerName$Builder allowed(java.lang.String)", + "public com.yahoo.jdisc.http.ConnectorConfig$ServerName$Builder allowed(java.util.Collection)", "public com.yahoo.jdisc.http.ConnectorConfig$ServerName build()" ], - "fields": [] + "fields": [ + "public java.util.List allowed" + ] }, "com.yahoo.jdisc.http.ConnectorConfig$ServerName": { "superClass": "com.yahoo.config.InnerNode", @@ -1215,7 +1219,9 @@ ], "methods": [ "public void <init>(com.yahoo.jdisc.http.ConnectorConfig$ServerName$Builder)", - "public java.lang.String fallback()" + "public java.lang.String fallback()", + "public java.util.List allowed()", + "public java.lang.String allowed(int)" ], "fields": [] }, diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java index dd5181d2bb5..c0b3a336a39 100644 --- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java +++ b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java @@ -14,11 +14,13 @@ import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.jmx.ConnectorServer; import org.eclipse.jetty.jmx.MBeanContainer; import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.SslConnectionFactory; +import org.eclipse.jetty.server.handler.ContextHandler; +import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.server.handler.HandlerCollection; +import org.eclipse.jetty.server.handler.HandlerWrapper; import org.eclipse.jetty.server.handler.StatisticsHandler; import org.eclipse.jetty.server.handler.gzip.GzipHandler; import org.eclipse.jetty.server.handler.gzip.GzipHttpOutputInterceptor; @@ -83,20 +85,13 @@ public class JettyHttpServer extends AbstractServerProvider { listenedPorts.add(connectorConfig.listenPort()); } - JDiscContext jDiscContext = new JDiscContext(filterBindings, - container, - janitor, - metric, - serverConfig); + JDiscContext jDiscContext = new JDiscContext(filterBindings, container, janitor, metric, serverConfig); ServletHolder jdiscServlet = new ServletHolder(new JDiscHttpServlet(jDiscContext)); List<JDiscServerConnector> connectors = Arrays.stream(server.getConnectors()) .map(JDiscServerConnector.class::cast) .collect(toList()); - - server.setHandler(getHandlerCollection(serverConfig, - connectors, - jdiscServlet)); + server.setHandler(createRootHandler(serverConfig, connectors, jdiscServlet)); this.metricsReporter = new ServerMetricReporter(metric, server); } @@ -136,38 +131,37 @@ public class JettyHttpServer extends AbstractServerProvider { } } - private HandlerCollection getHandlerCollection(ServerConfig serverConfig, - List<JDiscServerConnector> connectors, - ServletHolder jdiscServlet) { - ServletContextHandler servletContextHandler = createServletContextHandler(); - servletContextHandler.addServlet(jdiscServlet, "/*"); - - var proxyHandler = new HealthCheckProxyHandler(connectors); - proxyHandler.setHandler(servletContextHandler); - - List<ConnectorConfig> connectorConfigs = connectors.stream().map(JDiscServerConnector::connectorConfig).collect(toList()); - var authEnforcer = new TlsClientAuthenticationEnforcer(connectorConfigs); - authEnforcer.setHandler(proxyHandler); - - GzipHandler gzipHandler = newGzipHandler(serverConfig); - gzipHandler.setHandler(authEnforcer); - - var statisticsCollector = new HttpResponseStatisticsCollector(serverConfig.metric()); - statisticsCollector.setHandler(gzipHandler); - - StatisticsHandler statisticsHandler = newStatisticsHandler(); - statisticsHandler.setHandler(statisticsCollector); - - HandlerCollection handlerCollection = new HandlerCollection(); - handlerCollection.setHandlers(new Handler[] { statisticsHandler }); - return handlerCollection; + private HandlerCollection createRootHandler( + ServerConfig serverCfg, List<JDiscServerConnector> connectors, ServletHolder jdiscServlet) { + List<ConnectorConfig> connectorCfgs = connectors.stream().map(JDiscServerConnector::connectorConfig).toList(); + List<ContextHandler> perConnectorHandlers = new ArrayList<>(); + for (JDiscServerConnector connector : connectors) { + ConnectorConfig connectorCfg = connector.connectorConfig(); + List<HandlerWrapper> chain = new ArrayList<>(); + chain.add(newGenericStatisticsHandler()); + chain.add(newResponseStatisticsHandler(serverCfg)); + chain.add(newGzipHandler(serverCfg)); + if (connectorCfg.tlsClientAuthEnforcer().enable()) { + chain.add(newTlsClientAuthEnforcerHandler(connectorCfgs)); + } + if (connectorCfg.healthCheckProxy().enable()) { + chain.add(newHealthCheckProxyHandler(connectors)); + } else { + chain.add(newServletHandler(jdiscServlet)); + } + ContextHandler connectorRoot = newConnectorContextHandler(connector, connectorCfg); + addChainToRoot(connectorRoot, chain); + perConnectorHandlers.add(connectorRoot); + } + return new ContextHandlerCollection(perConnectorHandlers.toArray(new ContextHandler[0])); } - private ServletContextHandler createServletContextHandler() { - ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.NO_SECURITY | ServletContextHandler.NO_SESSIONS); - servletContextHandler.setContextPath("/"); - servletContextHandler.setDisplayName(getDisplayName(listenedPorts)); - return servletContextHandler; + private static void addChainToRoot(ContextHandler root, List<HandlerWrapper> chain) { + HandlerWrapper parent = root; + for (HandlerWrapper h : chain) { + parent.setHandler(h); + parent = h; + } } private static String getDisplayName(List<Integer> ports) { @@ -229,13 +223,44 @@ public class JettyHttpServer extends AbstractServerProvider { Server server() { return server; } - private StatisticsHandler newStatisticsHandler() { + private ServletContextHandler newServletHandler(ServletHolder servlet) { + var h = new ServletContextHandler(ServletContextHandler.NO_SECURITY | ServletContextHandler.NO_SESSIONS); + h.setContextPath("/"); + h.setDisplayName(getDisplayName(listenedPorts)); + h.addServlet(servlet, "/*"); + return h; + } + + private static ContextHandler newConnectorContextHandler(JDiscServerConnector connector, ConnectorConfig connectorCfg) { + ContextHandler ctxHandler = new ContextHandler(); + List<String> allowedServerNames = connectorCfg.serverName().allowed(); + if (allowedServerNames.isEmpty()) { + ctxHandler.setVirtualHosts(new String[]{"@%s".formatted(connector.getName())}); + } else { + ctxHandler.setVirtualHosts(allowedServerNames.toArray(new String[0])); + } + return ctxHandler; + } + + private static HealthCheckProxyHandler newHealthCheckProxyHandler(List<JDiscServerConnector> connectors) { + return new HealthCheckProxyHandler(connectors); + } + + private static TlsClientAuthenticationEnforcer newTlsClientAuthEnforcerHandler(List<ConnectorConfig> connectorCfgs) { + return new TlsClientAuthenticationEnforcer(connectorCfgs); + } + + private static HttpResponseStatisticsCollector newResponseStatisticsHandler(ServerConfig cfg) { + return new HttpResponseStatisticsCollector(cfg.metric()); + } + + private static StatisticsHandler newGenericStatisticsHandler() { StatisticsHandler statisticsHandler = new StatisticsHandler(); statisticsHandler.statsReset(); return statisticsHandler; } - private GzipHandler newGzipHandler(ServerConfig serverConfig) { + private static GzipHandler newGzipHandler(ServerConfig serverConfig) { GzipHandler gzipHandler = new GzipHandlerWithVaryHeaderFixed(); gzipHandler.setCompressionLevel(serverConfig.responseCompressionLevel()); gzipHandler.setInflateBufferSize(8 * 1024); diff --git a/container-core/src/main/resources/configdefinitions/jdisc.http.jdisc.http.connector.def b/container-core/src/main/resources/configdefinitions/jdisc.http.jdisc.http.connector.def index c0ad425fcc7..ecbc451ead1 100644 --- a/container-core/src/main/resources/configdefinitions/jdisc.http.jdisc.http.connector.def +++ b/container-core/src/main/resources/configdefinitions/jdisc.http.jdisc.http.connector.def @@ -132,3 +132,5 @@ http2.maxConcurrentStreams int default=4096 # Override the default server name when authority is missing from request. serverName.fallback string default="" +# The list of accepted server names. Empty list to accept any. Elements follows format of 'serverName.default'. +serverName.allowed[] string |