org.nosceon.titanite.Router Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2014 the original author or authors.
*
* Licensed 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
*
* http://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 org.nosceon.titanite;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import org.nosceon.titanite.body.EmptyBodyParser;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CompletionStage;
import java.util.function.BiFunction;
import java.util.function.Function;
import static java.util.Collections.emptyMap;
import static java.util.stream.Collectors.toList;
/**
* @author Johan Siebens
*/
final class Router {
private static final RoutingResult METHOD_NOT_ALLOWED = new RoutingResult(emptyMap(), EmptyBodyParser::new, (r) -> Response.methodNotAllowed().toFuture());
private static final RoutingResult NOT_FOUND = new RoutingResult(emptyMap(), EmptyBodyParser::new, (r) -> Response.notFound().toFuture());
private final List routes = new LinkedList<>();
Router(List routings) {
this.routes.addAll(routings);
}
RoutingResult find(HttpMethod httpMethod, String path) {
Method method = map(httpMethod);
List candidates =
this.routes
.stream()
.filter(r -> r.pattern().matches(path))
.collect(toList());
if (candidates.isEmpty()) {
return NOT_FOUND;
}
else {
return
candidates
.stream()
.filter(route -> route.hasMethod(method))
.findFirst()
.map(route -> {
ParameterizedPattern.Matcher matcher = route.pattern().matcher(path);
return
Method.OPTIONS.equals(method) ?
new RoutingResult(matcher.parameters(), route.bodyParser(), new CompositeHandler(allowedMethodsFilter(candidates), route.handler())) :
new RoutingResult(matcher.parameters(), route.bodyParser(), route.handler());
})
.orElseGet(() -> {
if (Method.OPTIONS.equals(method)) {
return new RoutingResult(emptyMap(), EmptyBodyParser::new, new CompositeHandler(allowedMethodsFilter(candidates), req -> Response.ok().toFuture()));
}
else if (Method.HEAD.equals(method)) {
return find(HttpMethod.GET, path);
}
else {
return METHOD_NOT_ALLOWED;
}
}
);
}
}
private BiFunction>, CompletionStage> allowedMethodsFilter(List candidates) {
return (req, h) -> h.apply(req).thenApply(resp -> resp.header(HttpHeaders.Names.ALLOW, allowedMethods(candidates)));
}
private String allowedMethods(List candidates) {
return candidates.stream().map(Route::method).distinct().map(Method::name).sorted().reduce("", (s, s2) -> s.length() == 0 ? s2 : s + ", " + s2);
}
private Method map(HttpMethod method) {
try {
return Method.valueOf(method.name());
}
catch (IllegalArgumentException e) {
return null;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy