summaryrefslogtreecommitdiffstats
path: root/container-disc
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorncs@verizonmedia.com>2020-11-16 11:19:22 +0100
committerBjørn Christian Seime <bjorncs@verizonmedia.com>2020-11-17 13:28:07 +0100
commitcdbf498c9182ac06bb21ce8ae7b745dd8c8f3c83 (patch)
tree21a21f94ef0d888d74597b6142956c1b41901b13 /container-disc
parente4c14623ad4ecbe6337a49d2176621c528bf7c22 (diff)
Support default request/response filters per connector
Filter requests using default request/response filter if no other filters matches the request uri.
Diffstat (limited to 'container-disc')
-rw-r--r--container-disc/src/main/java/com/yahoo/container/jdisc/FilterBindingsProvider.java98
-rw-r--r--container-disc/src/main/java/com/yahoo/container/jdisc/FilterUtil.java99
2 files changed, 84 insertions, 113 deletions
diff --git a/container-disc/src/main/java/com/yahoo/container/jdisc/FilterBindingsProvider.java b/container-disc/src/main/java/com/yahoo/container/jdisc/FilterBindingsProvider.java
index 195aee93246..6527a368113 100644
--- a/container-disc/src/main/java/com/yahoo/container/jdisc/FilterBindingsProvider.java
+++ b/container-disc/src/main/java/com/yahoo/container/jdisc/FilterBindingsProvider.java
@@ -1,16 +1,21 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.container.jdisc;
+import com.google.inject.Inject;
import com.yahoo.component.ComponentId;
+import com.yahoo.component.ComponentSpecification;
import com.yahoo.component.provider.ComponentRegistry;
import com.yahoo.container.di.componentgraph.Provider;
import com.yahoo.container.http.filter.FilterChainRepository;
import com.yahoo.jdisc.http.ServerConfig;
+import com.yahoo.jdisc.http.filter.RequestFilter;
+import com.yahoo.jdisc.http.filter.ResponseFilter;
import com.yahoo.jdisc.http.filter.SecurityRequestFilter;
+import com.yahoo.jdisc.http.filter.SecurityRequestFilterChain;
import com.yahoo.jdisc.http.server.jetty.FilterBindings;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.HashSet;
+import java.util.Set;
/**
* Provides filter bindings based on vespa config.
@@ -20,35 +25,100 @@ import java.util.List;
*/
public class FilterBindingsProvider implements Provider<FilterBindings> {
+ private static final ComponentId SEARCH_SERVER_COMPONENT_ID = ComponentId.fromString("SearchServer");
+
private final FilterBindings filterBindings;
+ @Inject
public FilterBindingsProvider(ComponentId componentId,
ServerConfig config,
FilterChainRepository filterChainRepository,
ComponentRegistry<SecurityRequestFilter> legacyRequestFilters) {
try {
- this.filterBindings = FilterUtil.setupFilters(
- componentId,
- legacyRequestFilters,
- toFilterSpecs(config.filter()),
- filterChainRepository);
+ FilterBindings.Builder builder = new FilterBindings.Builder();
+ configureLegacyFilters(builder, componentId, legacyRequestFilters);
+ configureFilters(builder, config, filterChainRepository);
+ this.filterBindings = builder.build();
} catch (Exception e) {
throw new RuntimeException(
"Invalid config for http server '" + componentId.getNamespace() + "': " + e.getMessage(), e);
}
}
- private List<FilterUtil.FilterSpec> toFilterSpecs(List<ServerConfig.Filter> inFilters) {
- List<FilterUtil.FilterSpec> outFilters = new ArrayList<>();
- for (ServerConfig.Filter inFilter : inFilters) {
- outFilters.add(new FilterUtil.FilterSpec(inFilter.id(), inFilter.binding()));
+ // TODO(gjoranv): remove
+ private static void configureLegacyFilters(
+ FilterBindings.Builder builder,
+ ComponentId id,
+ ComponentRegistry<SecurityRequestFilter> legacyRequestFilters) {
+ ComponentId serverName = id.getNamespace();
+ if (SEARCH_SERVER_COMPONENT_ID.equals(serverName) && !legacyRequestFilters.allComponents().isEmpty()) {
+ String filterId = "legacy-filters";
+ builder.addRequestFilter(filterId, SecurityRequestFilterChain.newInstance(legacyRequestFilters.allComponents()));
+ builder.addRequestFilterBinding(filterId, "http://*/*");
+ }
+ }
+
+ private static void configureFilters(
+ FilterBindings.Builder builder, ServerConfig config, FilterChainRepository filterRepository) {
+ addFilterInstances(builder, config, filterRepository);
+ addFilterBindings(builder, config, filterRepository);
+ addPortDefaultFilters(builder, config, filterRepository);
+ }
+
+ private static void addFilterInstances(
+ FilterBindings.Builder builder, ServerConfig config, FilterChainRepository filterRepository) {
+ Set<String> filterIds = new HashSet<>();
+ config.filter().forEach(filterBinding -> filterIds.add(filterBinding.id()));
+ config.defaultFilters().forEach(defaultFilter -> filterIds.add(defaultFilter.filterId()));
+ for (String filterId : filterIds) {
+ Object filterInstance = getFilterInstance(filterRepository, filterId);
+ if (filterInstance instanceof RequestFilter && filterInstance instanceof ResponseFilter) {
+ throw new IllegalArgumentException("The filter " + filterInstance.getClass().getName()
+ + " is unsupported since it's both a RequestFilter and a ResponseFilter.");
+ } else if (filterInstance instanceof RequestFilter) {
+ builder.addRequestFilter(filterId, (RequestFilter)filterInstance);
+ } else if (filterInstance instanceof ResponseFilter) {
+ builder.addResponseFilter(filterId, (ResponseFilter)filterInstance);
+ } else if (filterInstance == null) {
+ throw new IllegalArgumentException("No http filter with id " + filterId);
+ } else {
+ throw new IllegalArgumentException("Unknown filter type: " + filterInstance.getClass().getName());
+ }
+ }
+ }
+
+ private static void addFilterBindings(
+ FilterBindings.Builder builder, ServerConfig config, FilterChainRepository filterRepository) {
+ for (ServerConfig.Filter filterBinding : config.filter()) {
+ if (isRequestFilter(filterRepository, filterBinding.id())) {
+ builder.addRequestFilterBinding(filterBinding.id(), filterBinding.binding());
+ } else {
+ builder.addResponseFilterBinding(filterBinding.id(), filterBinding.binding());
+ }
+ }
+ }
+
+ private static void addPortDefaultFilters(
+ FilterBindings.Builder builder, ServerConfig config, FilterChainRepository filterRepository) {
+ for (ServerConfig.DefaultFilters defaultFilter : config.defaultFilters()) {
+ if (isRequestFilter(filterRepository, defaultFilter.filterId())) {
+ builder.setRequestFilterDefaultForPort(defaultFilter.filterId(), defaultFilter.localPort());
+ } else {
+ builder.setResponseFilterDefaultForPort(defaultFilter.filterId(), defaultFilter.localPort());
+ }
}
- return outFilters;
+ }
+
+ private static boolean isRequestFilter(FilterChainRepository filterRepository, String filterId) {
+ return getFilterInstance(filterRepository, filterId) instanceof RequestFilter;
+ }
+
+ private static Object getFilterInstance(FilterChainRepository filterRepository, String filterId) {
+ return filterRepository.getFilter(ComponentSpecification.fromString(filterId));
}
@Override public FilterBindings get() { return filterBindings; }
- @Override
- public void deconstruct() {}
+ @Override public void deconstruct() {}
}
diff --git a/container-disc/src/main/java/com/yahoo/container/jdisc/FilterUtil.java b/container-disc/src/main/java/com/yahoo/container/jdisc/FilterUtil.java
deleted file mode 100644
index 52829d6710e..00000000000
--- a/container-disc/src/main/java/com/yahoo/container/jdisc/FilterUtil.java
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.container.jdisc;
-
-import com.yahoo.component.ComponentId;
-import com.yahoo.component.ComponentSpecification;
-import com.yahoo.component.provider.ComponentRegistry;
-import com.yahoo.container.http.filter.FilterChainRepository;
-import com.yahoo.jdisc.http.filter.RequestFilter;
-import com.yahoo.jdisc.http.filter.ResponseFilter;
-import com.yahoo.jdisc.http.filter.SecurityRequestFilter;
-import com.yahoo.jdisc.http.filter.SecurityRequestFilterChain;
-import com.yahoo.jdisc.http.server.jetty.FilterBindings;
-
-import java.util.List;
-
-/**
- * Helper class to set up filter binding repositories based on config.
- *
- * @author Øyvind Bakksjø
- * @author bjorncs
- */
-class FilterUtil {
-
- private static final ComponentId SEARCH_SERVER_COMPONENT_ID = ComponentId.fromString("SearchServer");
-
- private final FilterBindings.Builder builder = new FilterBindings.Builder();
-
- private FilterUtil() {}
-
- private void configureFilters(List<FilterSpec> filtersConfig, FilterChainRepository filterChainRepository) {
- for (FilterSpec filterConfig : filtersConfig) {
- Object filter = filterChainRepository.getFilter(ComponentSpecification.fromString(filterConfig.getId()));
- if (filter == null) {
- throw new RuntimeException("No http filter with id " + filterConfig.getId());
- }
- addFilter(filter, filterConfig.getBinding(), filterConfig.getId());
- }
- }
-
- private void addFilter(Object filter, String binding, String filterId) {
- if (filter instanceof RequestFilter && filter instanceof ResponseFilter) {
- throw new RuntimeException("The filter " + filter.getClass().getName() +
- " is unsupported since it's both a RequestFilter and a ResponseFilter.");
- } else if (filter instanceof RequestFilter) {
- builder.addRequestFilter(filterId, binding, (RequestFilter) filter);
- } else if (filter instanceof ResponseFilter) {
- builder.addResponseFilter(filterId, binding, (ResponseFilter) filter);
- } else {
- throw new RuntimeException("Unknown filter type " + filter.getClass().getName());
- }
- }
-
- // TODO(gjoranv): remove
- private void configureLegacyFilters(ComponentId id, ComponentRegistry<SecurityRequestFilter> legacyRequestFilters) {
- ComponentId serverName = id.getNamespace();
- if (SEARCH_SERVER_COMPONENT_ID.equals(serverName) && !legacyRequestFilters.allComponents().isEmpty()) {
- builder.addRequestFilter(
- "legacy-filters", "http://*/*", SecurityRequestFilterChain.newInstance(legacyRequestFilters.allComponents()));
- }
- }
-
- /**
- * Populates binding repositories with filters based on config.
- */
- public static FilterBindings setupFilters(
- ComponentId componentId,
- ComponentRegistry<SecurityRequestFilter> legacyRequestFilters,
- List<FilterSpec> filtersConfig,
- FilterChainRepository filterChainRepository) {
- FilterUtil filterUtil = new FilterUtil();
-
- // TODO(gjoranv): remove
- filterUtil.configureLegacyFilters(componentId, legacyRequestFilters);
-
- filterUtil.configureFilters(filtersConfig, filterChainRepository);
-
- return filterUtil.builder.build();
- }
-
- public static class FilterSpec {
-
- private final String id;
- private final String binding;
-
- public FilterSpec(String id, String binding) {
- this.id = id;
- this.binding = binding;
- }
-
- public String getId() {
- return id;
- }
-
- public String getBinding() {
- return binding;
- }
- }
-
-}