/
PatternServiceRouteMapper.java
74 lines (66 loc) · 2.29 KB
/
PatternServiceRouteMapper.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package org.springframework.cloud.netflix.zuul.filters.discovery;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.util.StringUtils;
/**
* @author Stéphane Leroy
*
* This service route mapper use Java 7 RegEx named group feature to rewrite a discovered
* service Id into a route.
*
* Ex : If we want to map service Id <code>[rest-service-v1]</code> to
* <code>/v1/rest-service/**</code> route service pattern :
* <code>"(?<name>.*)-(?<version>v.*$)"</code> route pattern :
* <code>"${version}/${name}"</code>
*
* This implementation uses <code>Matcher.replaceFirst</code> so only one match will be
* replaced.
*/
public class PatternServiceRouteMapper implements ServiceRouteMapper {
private static final Pattern MULTIPLE_SLASH_PATTERN = Pattern.compile("/{2,}");
/**
* A RegExp Pattern that extract needed information from a service ID. Ex :
* "(?<name>.*)-(?<version>v.*$)"
*/
private Pattern servicePattern;
/**
* A RegExp that refer to named groups define in servicePattern. Ex :
* "${version}/${name}"
*/
private String routePattern;
public PatternServiceRouteMapper(String servicePattern, String routePattern) {
this.servicePattern = Pattern.compile(servicePattern);
this.routePattern = routePattern;
}
/**
* Use servicePattern to extract groups and routePattern to construct the route.
*
* If there is no matches, the serviceId is returned.
*
* @param serviceId service discovered name
* @return route path
*/
@Override
public String apply(String serviceId) {
Matcher matcher = this.servicePattern.matcher(serviceId);
String route = matcher.replaceFirst(this.routePattern);
route = cleanRoute(route);
return (StringUtils.hasText(route) ? route : serviceId);
}
/**
* Route with regex and replace can be a bit messy when used with conditional named
* group. We clean here first and trailing '/' and remove multiple consecutive '/'
* @param route
* @return
*/
private String cleanRoute(final String route) {
String routeToClean = MULTIPLE_SLASH_PATTERN.matcher(route).replaceAll("/");
if (routeToClean.startsWith("/")) {
routeToClean = routeToClean.substring(1);
}
if (routeToClean.endsWith("/")) {
routeToClean = routeToClean.substring(0, routeToClean.length() - 1);
}
return routeToClean;
}
}