in dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/DefaultRequestMappingRegistry.java [217:310]
public HandlerMeta lookup(HttpRequest request) {
if (tree == null) {
return null;
}
String stringPath = PathUtils.normalize(request.uri());
request.setAttribute(RestConstants.PATH_ATTRIBUTE, stringPath);
KeyString path = new KeyString(stringPath, restConfig.getCaseSensitiveMatchOrDefault());
List<Candidate> candidates = new ArrayList<>();
List<RequestMapping> partialMatches = new LinkedList<>();
tryMatch(request, path, candidates, partialMatches);
if (candidates.isEmpty()) {
int end = path.length();
if (end > 1 && restConfig.getTrailingSlashMatchOrDefault()) {
if (path.charAt(end - 1) == '/') {
tryMatch(request, path.subSequence(0, --end), candidates, partialMatches);
}
}
if (candidates.isEmpty()) {
for (int i = end - 1; i >= 0; i--) {
char ch = path.charAt(i);
if (ch == '/') {
break;
}
if (ch == '.' && restConfig.getSuffixPatternMatchOrDefault()) {
if (contentNegotiator.supportExtension(path.toString(i + 1, end))) {
tryMatch(request, path.subSequence(0, i), candidates, partialMatches);
if (!candidates.isEmpty()) {
break;
}
end = i;
}
}
if (ch == '~') {
request.setAttribute(RestConstants.SIG_ATTRIBUTE, path.toString(i + 1, end));
tryMatch(request, path.subSequence(0, i), candidates, partialMatches);
if (!candidates.isEmpty()) {
break;
}
}
}
}
}
int size = candidates.size();
if (size == 0) {
handleNoMatch(request, partialMatches);
return null;
}
if (size > 1) {
candidates.sort((c1, c2) -> {
int comparison = c1.expression.compareTo(c2.expression, stringPath);
if (comparison != 0) {
return comparison;
}
comparison = c1.mapping.compareTo(c2.mapping, request);
if (comparison != 0) {
return comparison;
}
return c1.variableMap.size() - c2.variableMap.size();
});
LOGGER.debug("Candidate rest mappings: {}", candidates);
Candidate first = candidates.get(0);
Candidate second = candidates.get(1);
if (first.mapping.compareTo(second.mapping, request) == 0) {
throw new RestMappingException(Messages.AMBIGUOUS_MAPPING, path, first, second);
}
}
Candidate winner = candidates.get(0);
RequestMapping mapping = winner.mapping;
HandlerMeta handler = winner.meta;
request.setAttribute(RestConstants.MAPPING_ATTRIBUTE, mapping);
request.setAttribute(RestConstants.HANDLER_ATTRIBUTE, handler);
LOGGER.debug("Matched rest mapping={}, method={}", mapping, handler.getMethod());
if (!winner.variableMap.isEmpty()) {
request.setAttribute(RestConstants.URI_TEMPLATE_VARIABLES_ATTRIBUTE, winner.variableMap);
}
ProducesCondition producesCondition = mapping.getProducesCondition();
if (producesCondition != null) {
request.setAttribute(RestConstants.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE, producesCondition.getMediaTypes());
}
return handler;
}