public NormalisedPathImpl(@Nonnull final String path, @Nullable final String apiPrefix) { original = requireNonNull(path, "A path is required"); normalised = normalise(apiPrefix, path); // We have normalized to start with a leading "/"; this will result in an empty path element pathParts = unmodifiableList(asList(normalised.substring(1).split("/"))); }
private static String normalise(@Nullable final String prefix, @Nonnull final String requestPath) { final String trimmedPath = trimPrefix(normaliseToLeadingSlash(prefix), normaliseToLeadingSlash(requestPath)); return normaliseToLeadingSlash(trimmedPath); }
/** * Tries to find the best fitting API path matching the given path and request method. * * @param path the requests path to find in API definition * @param method the {@link Request.Method} for the request * @return a {@link ApiOperationMatch} containing the information if the path is defined, the operation * is allowed and having the necessary {@link ApiOperation} if applicable */ @Nonnull public ApiOperationMatch findApiOperation(final String path, final Request.Method method) { // try to find possible matching paths regardless of HTTP method final NormalisedPath requestPath = new NormalisedPathImpl(path, apiPrefix); final List<ApiPath> matchingPaths = apiPathsGroupedByNumberOfParts .getOrDefault(requestPath.numberOfParts(), emptyList()).stream() .filter(p -> p.matches(requestPath)) .collect(toList()); if (matchingPaths.isEmpty()) { return ApiOperationMatch.MISSING_PATH; } // try to find the operation which fits the HTTP method, // choosing the most 'specific' path match from the candidates final PathItem.HttpMethod httpMethod = PathItem.HttpMethod.valueOf(method.name()); final Optional<ApiPath> matchingPathAndOperation = matchingPaths.stream() .filter(apiPath -> operations.contains(apiPath.original(), httpMethod)) .max(comparingInt(ApiOperationResolver::specificityScore)); return matchingPathAndOperation .map(match -> new ApiOperationMatch(new ApiOperation(match, requestPath, httpMethod, operations.get(match.original(), httpMethod)))) .orElse(ApiOperationMatch.NOT_ALLOWED_OPERATION); }