io.jmnarloch.spring.cloud.zuul.matcher.TrieRouteMatcher Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of zuul-trie-matcher-spring-cloud-starter Show documentation
Show all versions of zuul-trie-matcher-spring-cloud-starter Show documentation
Spring Cloud Netflix Zuul Trie Matcher
/**
* Copyright (c) 2015 the original author or authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.jmnarloch.spring.cloud.zuul.matcher;
import io.jmnarloch.spring.cloud.zuul.trie.Trie;
import org.springframework.cloud.netflix.zuul.filters.ProxyRouteLocator;
import org.springframework.util.Assert;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
/**
* A Trie based {@link RouteMatcher}.
*
* @author Jakub Narloch
*/
public class TrieRouteMatcher implements RouteMatcher {
/**
* The suffix used for wildcard route matching.
*/
private static final String WILDCARD = "**";
/**
* The instance of {@link TrieSupplier} used for instantiating new Tries.
*/
private final TrieSupplier trieSupplier;
/**
* Holds the reference to the Trie instance.
*/
private final AtomicReference> trie =
new AtomicReference>();
/**
* Creates new instance of {@link TrieRouteMatcher} with specific supplier.
*
* @param trieSupplier the Trie instance supplier
*/
public TrieRouteMatcher(TrieSupplier trieSupplier) {
Assert.notNull(trieSupplier, "Parameter 'trieSupplier' can not be null");
this.trieSupplier = trieSupplier;
}
/**
* {@inheritDoc}
*/
@Override
public void setRoutes(Map routes) {
final Trie trie = createTrie();
for (Map.Entry route : routes.entrySet()) {
trie.put(
path(route.getKey()),
new ProxyRouteSpecEntry(route.getKey(), route.getValue(), isWildcard(route.getKey()))
);
}
this.trie.set(trie);
}
/**
* {@inheritDoc}
*/
@Override
public ProxyRouteLocator.ProxyRouteSpec getMatchingRoute(String path) {
final ProxyRouteSpecEntry matching = trie.get().prefix(path);
if (matching == null) {
return null;
} else if (!matching.isWildcard() && !matchesExact(path, matching.getPath())) {
return null;
} else {
return matching.getProxyRouteSpec();
}
}
/**
* Normalizes the path by removing any wildcard symbol front the end.
*
* @param path the path
* @return the normalized path
*/
private String path(String path) {
if (path.endsWith(WILDCARD)) {
path = path.substring(0, path.length() - WILDCARD.length());
}
return path;
}
/**
* Returns whether the actual request path matches the configured route.
*
* @param pathSpec the configured path
* @param path the request path
* @return true if path matches
*/
private boolean matchesExact(String pathSpec, String path) {
return pathSpec.equals(path);
}
/**
* Returns whether
*
* @param key
* @return
*/
private boolean isWildcard(String key) {
return key.endsWith(WILDCARD);
}
/**
* Creates new instance of {@link Trie} by delegating to the provided {@link TrieSupplier} instance.
*
* @return the trie instance
*/
private Trie createTrie() {
return trieSupplier.createTrie();
}
/**
* A simple wrapper on the Trie value entry allowing to associate additional information with the route specs.
*
* @author Jakub Narloch
*/
private static class ProxyRouteSpecEntry {
/**
* The route path.
*/
private final String path;
/**
* The route spec.
*/
private final ProxyRouteLocator.ProxyRouteSpec proxyRouteSpec;
/**
* Whether the route is a wildcard.
*/
private final boolean wildcard;
/**
* Creates new instance of {@link ProxyRouteSpecEntry}
*
* @param path the route path
* @param proxyRouteSpec the route spec
* @param wildcard whether the route is wildcard
*/
public ProxyRouteSpecEntry(String path, ProxyRouteLocator.ProxyRouteSpec proxyRouteSpec, boolean wildcard) {
this.path = path;
this.proxyRouteSpec = proxyRouteSpec;
this.wildcard = wildcard;
}
/**
* Returns the route path.
*
* @return the route path
*/
public String getPath() {
return path;
}
/**
* Retrieves the route spec
*
* @return the route spec
*/
public ProxyRouteLocator.ProxyRouteSpec getProxyRouteSpec() {
return proxyRouteSpec;
}
/**
* Returns whether the path is a wildcard.
*
* @return the path wildcard
*/
public boolean isWildcard() {
return wildcard;
}
}
/**
* The Trie instance supplier, used whenever to instantiate and populate a Trie whenever a new list of routes is
* being provided.
*
* @author Jakub Narloch
*/
public interface TrieSupplier {
Trie createTrie();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy