diff options
author | Bjørn Christian Seime <bjorncs@verizonmedia.com> | 2020-11-18 12:37:35 +0100 |
---|---|---|
committer | Bjørn Christian Seime <bjorncs@verizonmedia.com> | 2020-11-18 12:37:35 +0100 |
commit | f0a6e9ec11836851e3029ca5f63b93243484059a (patch) | |
tree | fd2c9a63b27e88a12b2c7195ae9e08aedbec27f3 /config-model | |
parent | 337116886cdd4ab59c79a09e87316e3d29185386 (diff) |
Support default request/response filter chain per connector
Diffstat (limited to 'config-model')
7 files changed, 158 insertions, 12 deletions
diff --git a/config-model/pom.xml b/config-model/pom.xml index c0751431d03..56517b63884 100644 --- a/config-model/pom.xml +++ b/config-model/pom.xml @@ -46,6 +46,11 @@ <scope>test</scope> </dependency> <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> + <scope>test</scope> + </dependency> + <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>${protobuf.version}</version> diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/Container.java b/config-model/src/main/java/com/yahoo/vespa/model/container/Container.java index a7f5398c7b5..e8b56a6190a 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/Container.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/Container.java @@ -172,7 +172,7 @@ public abstract class Container extends AbstractService implements } private void initDefaultJettyConnector() { - defaultHttpServer.addConnector(new ConnectorFactory("SearchServer", getSearchPort())); + defaultHttpServer.addConnector(new ConnectorFactory.Builder("SearchServer", getSearchPort()).build()); } private ContainerServiceType myServiceType = null; diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/http/ConnectorFactory.java b/config-model/src/main/java/com/yahoo/vespa/model/container/http/ConnectorFactory.java index 2633fa958eb..9eab99af4d0 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/http/ConnectorFactory.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/http/ConnectorFactory.java @@ -9,6 +9,8 @@ import com.yahoo.vespa.model.container.component.SimpleComponent; import com.yahoo.vespa.model.container.http.ssl.DefaultSslProvider; import com.yahoo.vespa.model.container.http.ssl.SslProvider; +import java.util.Optional; + import static com.yahoo.component.ComponentSpecification.fromString; /** @@ -21,21 +23,29 @@ public class ConnectorFactory extends SimpleComponent implements ConnectorConfig private final String name; private final int listenPort; private final SslProvider sslProviderComponent; + private volatile ComponentId defaultRequestFilterChain; + private volatile ComponentId defaultResponseFilterChain; - public ConnectorFactory(String name, int listenPort) { - this(name, listenPort, new DefaultSslProvider(name)); + protected ConnectorFactory(String name, int listenPort, SslProvider sslProviderComponent) { + this(name, listenPort, sslProviderComponent, null, null); } - public ConnectorFactory(String name, - int listenPort, - SslProvider sslProviderComponent) { + protected ConnectorFactory( + String name, + int listenPort, + SslProvider sslProviderComponent, + ComponentId defaultRequestFilterChain, + ComponentId defaultResponseFilterChain) { super(new ComponentModel( - new BundleInstantiationSpecification(new ComponentId(name), - fromString("com.yahoo.jdisc.http.server.jetty.ConnectorFactory"), - fromString("jdisc_http_service")))); + new BundleInstantiationSpecification( + new ComponentId(name), + fromString("com.yahoo.jdisc.http.server.jetty.ConnectorFactory"), + fromString("jdisc_http_service")))); this.name = name; this.listenPort = listenPort; this.sslProviderComponent = sslProviderComponent; + this.defaultRequestFilterChain = defaultRequestFilterChain; + this.defaultResponseFilterChain = defaultResponseFilterChain; addChild(sslProviderComponent); inject(sslProviderComponent); } @@ -55,4 +65,43 @@ public class ConnectorFactory extends SimpleComponent implements ConnectorConfig return listenPort; } + public Optional<ComponentId> getDefaultRequestFilterChain() { return Optional.ofNullable(defaultRequestFilterChain); } + + public Optional<ComponentId> getDefaultResponseFilterChain() { return Optional.ofNullable(defaultResponseFilterChain); } + + public void setDefaultRequestFilterChain(ComponentId filterChain) { this.defaultRequestFilterChain = filterChain; } + + public void setDefaultResponseFilterChain(ComponentId filterChain) { this.defaultResponseFilterChain = filterChain; } + + public static class Builder { + private final String name; + private final int listenPort; + + private SslProvider sslProvider; + private ComponentId defaultRequestFilterChain; + private ComponentId defaultResponseFilterChain; + + public Builder(String name, int listenPort) { + this.name = name; + this.listenPort = listenPort; + } + + public Builder setSslProvider(SslProvider sslProvider) { + this.sslProvider = sslProvider; return this; + } + + public Builder setDefaultRequestFilterChain(ComponentId filterChain) { + this.defaultRequestFilterChain = filterChain; return this; + } + + public Builder setDefaultResponseFilterChain(ComponentId filterChain) { + this.defaultResponseFilterChain = filterChain; + return this; + } + + public ConnectorFactory build() { + SslProvider sslProvider = this.sslProvider != null ? this.sslProvider : new DefaultSslProvider(name); + return new ConnectorFactory(name, listenPort, sslProvider, defaultRequestFilterChain, defaultResponseFilterChain); + } + } } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/http/Http.java b/config-model/src/main/java/com/yahoo/vespa/model/container/http/Http.java index f58f5faa382..1ed043857e2 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/http/Http.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/http/Http.java @@ -79,6 +79,7 @@ public class Http extends AbstractConfigProducer<AbstractConfigProducer<?>> impl .id(binding.chainId().stringValue()) .binding(binding.binding().patternString())); } + populateDefaultFiltersConfig(builder, httpServer); } @Override @@ -96,4 +97,19 @@ public class Http extends AbstractConfigProducer<AbstractConfigProducer<?>> impl throw new RuntimeException("Can't find filter " + binding.chainId() + " for binding " + binding.binding()); } } + + private static void populateDefaultFiltersConfig(ServerConfig.Builder builder, JettyHttpServer httpServer) { + if (httpServer != null) { + for (ConnectorFactory connector : httpServer.getConnectorFactories()) { + connector.getDefaultRequestFilterChain().ifPresent( + filterChain -> builder.defaultFilters(new ServerConfig.DefaultFilters.Builder() + .filterId(filterChain.stringValue()) + .localPort(connector.getListenPort()))); + connector.getDefaultResponseFilterChain().ifPresent( + filterChain -> builder.defaultFilters(new ServerConfig.DefaultFilters.Builder() + .filterId(filterChain.stringValue()) + .localPort(connector.getListenPort()))); + } + } + } } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/http/xml/JettyConnectorBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/container/http/xml/JettyConnectorBuilder.java index 505cc81c0cb..9f25550418e 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/http/xml/JettyConnectorBuilder.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/http/xml/JettyConnectorBuilder.java @@ -1,6 +1,7 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.model.container.http.xml; +import com.yahoo.component.ComponentId; import com.yahoo.config.model.builder.xml.XmlHelper; import com.yahoo.config.model.deploy.DeployState; import com.yahoo.config.model.producer.AbstractConfigProducer; @@ -30,9 +31,15 @@ public class JettyConnectorBuilder extends VespaDomBuilder.DomConfigProducerBuil protected ConnectorFactory doBuild(DeployState deployState, AbstractConfigProducer ancestor, Element serverSpec) { String name = XmlHelper.getIdString(serverSpec); int port = HttpBuilder.readPort(new ModelElement(serverSpec), deployState.isHosted(), deployState.getDeployLogger()); - + ConnectorFactory.Builder builder = new ConnectorFactory.Builder(name, port); + XmlHelper.getOptionalAttribute(serverSpec, "default-request-chain") + .map(ComponentId::new) + .ifPresent(builder::setDefaultRequestFilterChain); + XmlHelper.getOptionalAttribute(serverSpec, "default-response-chain") + .map(ComponentId::new) + .ifPresent(builder::setDefaultResponseFilterChain); SslProvider sslProviderComponent = getSslConfigComponents(name, serverSpec); - return new ConnectorFactory(name, port, sslProviderComponent); + return builder.setSslProvider(sslProviderComponent).build(); } SslProvider getSslConfigComponents(String serverName, Element serverSpec) { diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java index fc604c6174a..c8f2bd08ea5 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java @@ -362,7 +362,7 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> { if(cluster.getHttp().getHttpServer().isEmpty()) { JettyHttpServer defaultHttpServer = new JettyHttpServer(new ComponentId("DefaultHttpServer"), cluster, cluster.isHostedVespa()); cluster.getHttp().setHttpServer(defaultHttpServer); - defaultHttpServer.addConnector(new ConnectorFactory("SearchServer", Defaults.getDefaults().vespaWebServicePort())); + defaultHttpServer.addConnector(new ConnectorFactory.Builder("SearchServer", Defaults.getDefaults().vespaWebServicePort()).build()); } } diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/http/DefaultFilterTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/http/DefaultFilterTest.java new file mode 100644 index 00000000000..e5c01989c22 --- /dev/null +++ b/config-model/src/test/java/com/yahoo/vespa/model/container/http/DefaultFilterTest.java @@ -0,0 +1,69 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.model.container.http; + +import com.yahoo.config.model.builder.xml.test.DomBuilderTest; +import com.yahoo.config.model.deploy.DeployState; +import com.yahoo.container.core.ChainsConfig; +import com.yahoo.jdisc.http.ServerConfig; +import com.yahoo.vespa.model.container.component.BindingPattern; +import com.yahoo.vespa.model.container.component.UserBindingPattern; +import com.yahoo.vespa.model.container.xml.ContainerModelBuilder; +import org.junit.Test; +import org.w3c.dom.Element; + +import java.util.Set; + +import static java.util.stream.Collectors.toSet; +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author bjorncs + */ +public class DefaultFilterTest extends DomBuilderTest { + + private void buildContainerCluster(Element containerElem) { + new ContainerModelBuilder(true, ContainerModelBuilder.Networking.enable).build(DeployState.createTestState(), null, null, root, containerElem); + root.freezeModelTopology(); + } + + @Test + public void default_request_and_response_filters_in_services_xml_are_listen_in_server_config() { + BindingPattern binding = UserBindingPattern.fromHttpPath("/my-chain-binding"); + Element xml = parse( + "<container version='1.0'>", + " <http>", + " <filtering>", + " <request-chain id='request-chain-with-binding'>", + " <binding>" + binding.patternString() + "</binding>", + " </request-chain>", + " <response-chain id='response-chain-with-binding'>", + " <binding>" + binding.patternString() + "</binding>", + " </response-chain>", + " <request-chain id='my-default-request-chain'/>" + + " <response-chain id='my-default-response-chain'/>", + " </filtering>", + " <server id='server1' port='8000' default-request-chain=\"my-default-request-chain\" default-response-chain=\"my-default-response-chain\"/>", + " <server id='server2' port='9000' />", + " </http>", + "</container>"); + buildContainerCluster(xml); + + assertDefaultFiltersInConfig(root.getConfig(ServerConfig.class, "container/http/jdisc-jetty/server1")); + assertDefaultFiltersInConfig(root.getConfig(ServerConfig.class, "container/http/jdisc-jetty/server2")); + + ChainsConfig chainsConfig = root.getConfig(ChainsConfig.class, "container/filters/chain"); + Set<String> chainsIds = chainsConfig.chains().stream().map(ChainsConfig.Chains::id).collect(toSet()); + assertThat(chainsIds) + .containsExactlyInAnyOrder( + "request-chain-with-binding", "response-chain-with-binding", "my-default-request-chain", "my-default-response-chain"); + } + + private static void assertDefaultFiltersInConfig(ServerConfig config) { + assertThat(config.defaultFilters()) + .containsExactlyInAnyOrder( + new ServerConfig.DefaultFilters(new ServerConfig.DefaultFilters.Builder() + .filterId("my-default-request-chain").localPort(8000)), + new ServerConfig.DefaultFilters(new ServerConfig.DefaultFilters.Builder() + .filterId("my-default-response-chain").localPort(8000))); + } +} |