com.linecorp.armeria.server.PathMapping Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of armeria-shaded Show documentation
Show all versions of armeria-shaded Show documentation
Asynchronous HTTP/2 RPC/REST client/server library built on top of Java 8, Netty, Thrift and GRPC (armeria-shaded)
/*
* Copyright 2015 LINE Corporation
*
* LINE Corporation licenses this file to you 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:
*
* https://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 com.linecorp.armeria.server;
import static java.util.Objects.requireNonNull;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Pattern;
import com.linecorp.armeria.server.docs.DocService;
import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.Tag;
/**
* Matches the absolute path part of a URI and extracts path parameters from it.
*/
public interface PathMapping {
/**
* Creates a new {@link PathMapping} that matches the specified {@code pathPattern}. e.g.
*
* - {@code /login} (no path parameters)
* - {@code /users/{userId}} (curly-brace style)
* - {@code /list/:productType/by/:ordering} (colon style)
* - {@code exact:/foo/bar} (exact match)
* - {@code prefix:/files} (prefix match)
* glob:/~*/downloads/**
(glob pattern)
* - {@code regex:^/files/(?
.*)$} (regular expression)
*
*
* @throws IllegalArgumentException if the specified path pattern is invalid
*/
static PathMapping of(String pathPattern) {
requireNonNull(pathPattern, "pathPattern");
if (pathPattern.startsWith(ExactPathMapping.PREFIX)) {
return ofExact(pathPattern.substring(ExactPathMapping.PREFIX_LEN));
}
if (pathPattern.startsWith(PrefixPathMapping.PREFIX)) {
return ofPrefix(pathPattern.substring(PrefixPathMapping.PREFIX_LEN));
}
if (pathPattern.startsWith(GlobPathMapping.PREFIX)) {
return ofGlob(pathPattern.substring(GlobPathMapping.PREFIX_LEN));
}
if (pathPattern.startsWith(RegexPathMapping.PREFIX)) {
return ofRegex(pathPattern.substring(RegexPathMapping.PREFIX_LEN));
}
if (!pathPattern.startsWith("/")) {
throw new IllegalArgumentException(
"pathPattern: " + pathPattern + " (not an absolute path or a unknown pattern type)");
}
if (!pathPattern.contains("{") && !pathPattern.contains(":")) {
return ofExact(pathPattern);
}
return new DefaultPathMapping(pathPattern);
}
/**
* Creates a new {@link PathMapping} that matches a {@linkplain ServiceRequestContext#path() path} with
* the specified regular expression and extracts the values of the named groups.
* e.g. {@code "^/users/(?[0-9]+)$"} will extract the second numeric part of the path into
* the {@code "userId"} path parameter.
*/
static PathMapping ofRegex(Pattern regex) {
return new RegexPathMapping(regex);
}
/**
* Creates a new {@link PathMapping} that matches a {@linkplain ServiceRequestContext#path() path} with
* the specified regular expression and extracts the values of the named groups.
* e.g. {@code "^/users/(?[0-9]+)$"} will extract the second numeric part of the path into
* the {@code "userId"} path parameter.
*/
static PathMapping ofRegex(String regex) {
return ofRegex(Pattern.compile(requireNonNull(regex, "regex")));
}
/**
* Creates a new {@link PathMapping} that matches a {@linkplain ServiceRequestContext#path() path} with
* the specified glob expression, where {@code "*"} matches a path component non-recursively and
* {@code "**"} matches path components recursively.
*/
static PathMapping ofGlob(String glob) {
requireNonNull(glob, "glob");
if (glob.startsWith("/") && !glob.contains("*")) {
// Does not have a pattern matcher.
return ofExact(glob);
}
return new GlobPathMapping(glob);
}
/**
* Creates a new {@link PathMapping} that matches a {@linkplain ServiceRequestContext#path() path}
* under the specified directory prefix. It also removes the specified directory prefix from the matched
* path so that {@link ServiceRequestContext#path()} does not have the specified directory prefix.
* For example, when {@code pathPrefix} is {@code "/foo/"}:
*
* - {@code "/foo/"} translates to {@code "/"}
* - {@code "/foo/bar"} translates to {@code "/bar"}
* - {@code "/foo/bar/baz"} translates to {@code "/bar/baz"}
*
* This method is a shortcut to {@link #ofPrefix(String, boolean) ofPrefix(pathPrefix, true)}.
*/
static PathMapping ofPrefix(String pathPrefix) {
return ofPrefix(pathPrefix, true);
}
/**
* Creates a new {@link PathMapping} that matches a {@linkplain ServiceRequestContext#path() path}
* under the specified directory prefix. When {@code stripPrefix} is {@code true}, it also removes the
* specified directory prefix from the matched path so that {@link ServiceRequestContext#path()}
* does not have the specified directory prefix. For example, when {@code pathPrefix} is {@code "/foo/"}:
*
* - {@code "/foo/"} translates to {@code "/"}
* - {@code "/foo/bar"} translates to {@code "/bar"}
* - {@code "/foo/bar/baz"} translates to {@code "/bar/baz"}
*
*/
static PathMapping ofPrefix(String pathPrefix, boolean stripPrefix) {
requireNonNull(pathPrefix, "pathPrefix");
if ("/".equals(pathPrefix)) {
// Every path starts with '/'.
return ofCatchAll();
}
return new PrefixPathMapping(pathPrefix, stripPrefix);
}
/**
* Creates a new {@link PathMapping} that performs an exact match.
*/
static PathMapping ofExact(String exactPath) {
return new ExactPathMapping(exactPath);
}
/**
* Returns a singleton {@link PathMapping} that always matches any path.
*/
static PathMapping ofCatchAll() {
return CatchAllPathMapping.INSTANCE;
}
/**
* Matches the specified {@code path} and extracts the path parameters from it.
*
* @param mappingCtx a context to find the {@link Service}.
*
* @return a non-empty {@link PathMappingResult} if the specified {@code path} matches this mapping.
* {@link PathMappingResult#empty()} if not matches.
*/
PathMappingResult apply(PathMappingContext mappingCtx);
/**
* Returns the names of the path parameters extracted by this mapping.
*/
Set paramNames();
/**
* Returns the logger name.
*
* @return the logger name whose components are separated by a dot (.)
*/
String loggerName();
/**
* Returns the value of the {@code "pathMapping"} {@link Tag} in a {@link Meter}.
*/
String meterTag();
/**
* Returns the exact path of this path mapping if it is an exact path mapping, or {@link Optional#empty}
* otherwise. This can be useful for services which provide logic after scanning the server's mapped
* services, e.g. {@link DocService}
*/
Optional exactPath();
/**
* Returns the prefix of this path mapping if it is a prefix mapping, or {@link Optional#empty}
* otherwise. This can be useful for services which provide logic after scanning the server's mapped
* services, e.g. {@link DocService}
*
* @return the prefix that ends with '/' if this mapping is a prefix mapping
*/
Optional prefix();
/**
* Returns the path of this path mapping if it is able to be added to a trie.
*/
default Optional triePath() {
return Optional.empty();
}
/**
* Returns the complexity of this path mapping. It would be increased if this path mapping has
* more conditions to check.
*/
default int complexity() {
return 0;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy