All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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