public HandlerMeta lookup()

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;
    }