/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF 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 * * 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.jooby; import java.nio.file.Path; import java.util.Optional; import java.util.concurrent.Executor; import java.util.function.Predicate; import org.jooby.Route.Mapper; import org.jooby.handlers.AssetHandler; /** * Route DSL. Constructs and creates several flavors of jooby routes. * * @author edgar * @since 0.16.0 */ public interface Router { /** * Import content from provide application (routes, parsers/renderers, start/stop callbacks, ... * etc.). * * @param app Routes provider. * @return This jooby instance. */ Router use(final Jooby app); /** * Import content from provide application (routes, parsers/renderers, start/stop callbacks, ... * etc.). Routes will be mounted at the provided path. * * @param path Path to mount the given app. * @param app Routes provider. * @return This jooby instance. */ Router use(final String path, final Jooby app); /** * Define one or more routes under the same namespace: * * <pre> * { * use("/pets") * .get("/:id", req {@literal ->} db.get(req.param("id").value())) * .get(() {@literal ->} db.values()); * } * </pre> * * @param pattern Global pattern to use. * @return A route namespace. */ Route.Group use(String pattern); /** * Append a new filter that matches any method under the given path. * * @param path A path pattern. * @param filter A filter to execute. * @return A new route definition. */ Route.Definition use(String path, Route.Filter filter); /** * Append a new filter that matches the given method and path. * * @param method A HTTP method. * @param path A path pattern. * @param filter A filter to execute. * @return A new route definition. */ Route.Definition use(String method, String path, Route.Filter filter); /** * Append a new route handler that matches the given method and path. Like * {@link #use(String, String, org.jooby.Route.Filter)} but you don't have to explicitly call * {@link Route.Chain#next(Request, Response)}. * * @param method A HTTP method. * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition use(String method, String path, Route.Handler handler); /** * Append a new route handler that matches any method under the given path. Like * {@link #use(String, org.jooby.Route.Filter)} but you don't have to explicitly call * {@link Route.Chain#next(Request, Response)}. * * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition use(String path, Route.Handler handler); /** * Append a new route handler that matches any method under the given path. * * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition use(String path, Route.OneArgHandler handler); /** * Append a route that matches the HTTP GET method: * * <pre> * get("/", (req, rsp) {@literal ->} { * rsp.send(something); * }); * </pre> * * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition get(String path, Route.Handler handler); /** * Append two routes that matches the HTTP GET method on the same handler: * * <pre> * get("/model", "/mode/:id", (req, rsp) {@literal ->} { * rsp.send(req.param("id").toOptional(String.class)); * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection get(String path1, String path2, Route.Handler handler); /** * Append three routes that matches the HTTP GET method on the same handler: * * <pre> * get("/p1", "/p2", "/p3", (req, rsp) {@literal ->} { * rsp.send(req.path()); * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param path3 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection get(String path1, String path2, String path3, Route.Handler handler); /** * Append route that matches the HTTP GET method: * * <pre> * get("/", req {@literal ->} { * return "hello"; * }); * </pre> * * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition get(String path, Route.OneArgHandler handler); /** * Append three routes that matches the HTTP GET method on the same handler: * * <pre> * get("/model", "/model/:id", req {@literal ->} { * return req.param("id").toOptional(String.class); * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection get(String path1, String path2, Route.OneArgHandler handler); /** * Append three routes that matches the HTTP GET method on the same handler: * * <pre> * get("/p1", "/p2", "/p3", req {@literal ->} { * return req.path(); * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param path3 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection get(String path1, String path2, String path3, Route.OneArgHandler handler); /** * Append route that matches HTTP GET method: * * <pre> * get("/", () {@literal ->} * "hello" * ); * </pre> * * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition get(String path, Route.ZeroArgHandler handler); /** * Append three routes that matches the HTTP GET method on the same handler: * * <pre> * get("/p1", "/p2", () {@literal ->} { * return "OK"; * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection get(String path1, String path2, Route.ZeroArgHandler handler); /** * Append three routes that matches HTTP GET method on the same handler: * * <pre> * get("/p1", "/p2", "/p3", () {@literal ->} { * return "OK"; * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param path3 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection get(String path1, String path2, String path3, Route.ZeroArgHandler handler); /** * Append a filter that matches HTTP GET method: * * <pre> * get("/", (req, rsp, chain) {@literal ->} { * chain.next(req, rsp); * }); * </pre> * * @param path A path pattern. * @param filter A filter to execute. * @return A new route definition. */ Route.Definition get(String path, Route.Filter filter); /** * Append three routes that matches the HTTP GET method on the same handler: * * <pre> * get("/model", "/model/:id", (req, rsp, chain) {@literal ->} { * req.param("id").toOptional(String.class); * chain.next(req, rsp); * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param filter A filter to execute. * @return A new route definition. */ Route.Collection get(String path1, String path2, Route.Filter filter); /** * Append three routes that supports HTTP GET method on the same handler: * * <pre> * get("/p1", "/p2", "/p3", (req, rsp, chain) {@literal ->} { * chain.next(req, rsp); * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param path3 A path pattern. * @param filter A filter to execute. * @return A new route definition. */ Route.Collection get(String path1, String path2, String path3, Route.Filter filter); /** * Append a route that supports HTTP POST method: * * <pre> * post("/", (req, rsp) {@literal ->} { * rsp.send(something); * }); * </pre> * * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition post(String path, Route.Handler handler); /** * Append three routes that supports HTTP POST method on the same handler: * * <pre> * post("/p1", "/p2", (req, rsp) {@literal ->} { * rsp.send(req.path()); * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection post(String path1, String path2, Route.Handler handler); /** * Append three routes that supports HTTP POST method on the same handler: * * <pre> * post("/p1", "/p2", "/p3", (req, rsp) {@literal ->} { * rsp.send(req.path()); * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param path3 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection post(String path1, String path2, String path3, Route.Handler handler); /** * Append route that supports HTTP POST method: * * <pre> * post("/", req {@literal ->} * "hello" * ); * </pre> * * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition post(String path, Route.OneArgHandler handler); /** * Append three routes that supports HTTP POST method on the same handler: * * <pre> * post("/p1", "/p2", req {@literal ->} { * return req.path(); * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection post(String path1, String path2, Route.OneArgHandler handler); /** * Append three routes that supports HTTP POST method on the same handler: * * <pre> * post("/p1", "/p2", "/p3", req {@literal ->} { * return req.path(); * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param path3 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection post(String path1, String path2, String path3, Route.OneArgHandler handler); /** * Append route that supports HTTP POST method: * * <pre> * post("/", () {@literal ->} * "hello" * ); * </pre> * * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition post(String path, Route.ZeroArgHandler handler); /** * Append three routes that supports HTTP POST method on the same handler: * * <pre> * post("/p1", "/p2", {@literal ->} { * return "OK"; * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection post(String path1, String path2, Route.ZeroArgHandler handler); /** * Append three routes that supports HTTP POST method on the same handler: * * <pre> * post("/p1", "/p2", "/p3", () {@literal ->} { * return "OK"; * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param path3 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection post(String path1, String path2, String path3, Route.ZeroArgHandler handler); /** * Append a route that supports HTTP POST method: * * <pre> * post("/", (req, rsp, chain) {@literal ->} { * chain.next(req, rsp); * }); * </pre> * * @param path A path pattern. * @param filter A filter to execute. * @return A new route definition. */ Route.Definition post(String path, Route.Filter filter); /** * Append three routes that supports HTTP POST method on the same handler: * * <pre> * post("/p1", "/p2",(req, rsp, chain) {@literal ->} { * chain.next(req, rsp); * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param filter A filter to execute. * @return A new route definition. */ Route.Collection post(String path1, String path2, Route.Filter filter); /** * Append three routes that supports HTTP POST method on the same handler: * * <pre> * post("/p1", "/p2", "/p3", (req, rsp, chain) {@literal ->} { * chain.next(req, rsp); * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param path3 A path pattern. * @param filter A filter to execute. * @return A new route definition. */ Route.Collection post(String path1, String path2, String path3, Route.Filter filter); /** * Append a route that supports HTTP HEAD method: * * <pre> * post("/", (req, rsp) {@literal ->} { * rsp.send(something); * }); * </pre> * * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition head(String path, Route.Handler handler); /** * Append route that supports HTTP HEAD method: * * <pre> * head("/", req {@literal ->} * "hello" * ); * </pre> * * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition head(String path, Route.OneArgHandler handler); /** * Append route that supports HTTP HEAD method: * * <pre> * head("/", () {@literal ->} * "hello" * ); * </pre> * * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition head(String path, Route.ZeroArgHandler handler); /** * Append a route that supports HTTP HEAD method: * * <pre> * post("/", (req, rsp, chain) {@literal ->} { * chain.next(req, rsp); * }); * </pre> * * @param path A path pattern. * @param filter A filter to execute. * @return A new route definition. */ Route.Definition head(String path, Route.Filter filter); /** * Append a new route that automatically handles HEAD request from existing GET routes. * * <pre> * { * head(); * } * </pre> * * @return A new route definition. */ Route.Definition head(); /** * Append a route that supports HTTP OPTIONS method: * * <pre> * options("/", (req, rsp) {@literal ->} { * rsp.header("Allow", "GET, POST"); * }); * </pre> * * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition options(String path, Route.Handler handler); /** * Append route that supports HTTP OPTIONS method: * * <pre> * options("/", req {@literal ->} * return Results.with(200).header("Allow", "GET, POST") * ); * </pre> * * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition options(String path, Route.OneArgHandler handler); /** * Append route that supports HTTP OPTIONS method: * * <pre> * options("/", () {@literal ->} * return Results.with(200).header("Allow", "GET, POST") * ); * </pre> * * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition options(String path, Route.ZeroArgHandler handler); /** * Append a route that supports HTTP OPTIONS method: * * <pre> * options("/", (req, rsp, chain) {@literal ->} { * rsp.header("Allow", "GET, POST"); * chain.next(req, rsp); * }); * </pre> * * @param path A path pattern. * @param filter A callback to execute. * @return A new route definition. */ Route.Definition options(String path, Route.Filter filter); /** * Append a new route that automatically handles OPTIONS requests. * * <pre> * get("/", (req, rsp) {@literal ->} { * rsp.send(something); * }); * * post("/", (req, rsp) {@literal ->} { * rsp.send(something); * }); * * options("/"); * </pre> * * <code>OPTIONS /</code> produces a response with a Allow header set to: GET, POST. * * @return A new route definition. */ Route.Definition options(); /** * Append route that supports HTTP PUT method: * * <pre> * put("/", (req, rsp) {@literal ->} { * rsp.send(something); * }); * </pre> * * @param path A path pattern. * @param handler A route to execute. * @return A new route definition. */ Route.Definition put(String path, Route.Handler handler); /** * Append three routes that supports HTTP PUT method on the same handler: * * <pre> * put("/p1", "/p2", (req, rsp) {@literal ->} { * rsp.send(req.path()); * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection put(String path1, String path2, Route.Handler handler); /** * Append three routes that supports HTTP PUT method on the same handler: * * <pre> * put("/p1", "/p2", "/p3", (req, rsp) {@literal ->} { * rsp.send(req.path()); * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param path3 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection put(String path1, String path2, String path3, Route.Handler handler); /** * Append route that supports HTTP PUT method: * * <pre> * put("/", req {@literal ->} * return Results.accepted(); * ); * </pre> * * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition put(String path, Route.OneArgHandler handler); /** * Append three routes that supports HTTP PUT method on the same handler: * * <pre> * put("/p1", "/p2", req {@literal ->} { * return req.path(); * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection put(String path1, String path2, Route.OneArgHandler handler); /** * Append three routes that supports HTTP PUT method on the same handler: * * <pre> * put("/p1", "/p2", "/p3", req {@literal ->} { * return req.path(); * }); * </pre> * * This is a singleton route so make sure you don't share or use global variables. * * @param path1 A path pattern. * @param path2 A path pattern. * @param path3 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection put(String path1, String path2, String path3, Route.OneArgHandler handler); /** * Append route that supports HTTP PUT method: * * <pre> * put("/", () {@literal ->} { * return Results.accepted() * }); * </pre> * * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition put(String path, Route.ZeroArgHandler handler); /** * Append three routes that supports HTTP PUT method on the same handler: * * <pre> * put("/p1", "/p2", req {@literal ->} { * return req.path(); * }); * </pre> * * This is a singleton route so make sure you don't share or use global variables. * * @param path1 A path pattern. * @param path2 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection put(String path1, String path2, Route.ZeroArgHandler handler); /** * Append three routes that supports HTTP PUT method on the same handler: * * <pre> * put("/p1", "/p2", "/p3", req {@literal ->} { * return req.path(); * }); * </pre> * * This is a singleton route so make sure you don't share or use global variables. * * @param path1 A path pattern. * @param path2 A path pattern. * @param path3 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection put(String path1, String path2, String path3, Route.ZeroArgHandler handler); /** * Append route that supports HTTP PUT method: * * <pre> * put("/", (req, rsp, chain) {@literal ->} { * chain.next(req, rsp); * }); * </pre> * * @param path A path pattern. * @param filter A callback to execute. * @return A new route definition. */ Route.Definition put(String path, Route.Filter filter); /** * Append three routes that supports HTTP PUT method on the same handler: * * <pre> * put("/p1", "/p2", (req, rsp, chain) {@literal ->} { * chain.next(req, rsp); * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param filter A filter to execute. * @return A new route definition. */ Route.Collection put(String path1, String path2, Route.Filter filter); /** * Append three routes that supports HTTP PUT method on the same handler: * * <pre> * put("/p1", "/p2", "/p3", (req, rsp, chain) {@literal ->} { * chain.next(req, rsp); * }); * </pre> * * This is a singleton route so make sure you don't share or use global variables. * * @param path1 A path pattern. * @param path2 A path pattern. * @param path3 A path pattern. * @param filter A filter to execute. * @return A new route definition. */ Route.Collection put(String path1, String path2, String path3, Route.Filter filter); /** * Append route that supports HTTP PATCH method: * * <pre> * patch("/", (req, rsp) {@literal ->} { * rsp.send(something); * }); * </pre> * * @param path A path pattern. * @param handler A route to execute. * @return A new route definition. */ Route.Definition patch(String path, Route.Handler handler); /** * Append three routes that supports HTTP PATCH method on the same handler: * * <pre> * patch("/p1", "/p2", (req, rsp) {@literal ->} { * rsp.send(something); * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection patch(String path1, String path2, Route.Handler handler); /** * Append three routes that supports HTTP PATCH method on the same handler: * * <pre> * patch("/p1", "/p2", "/p3", (req, rsp) {@literal ->} { * rsp.send(something); * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param path3 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection patch(String path1, String path2, String path3, Route.Handler handler); /** * Append route that supports HTTP PATCH method: * * <pre> * patch("/", req {@literal ->} * Results.ok() * ); * </pre> * * This is a singleton route so make sure you don't share or use global variables. * * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition patch(String path, Route.OneArgHandler handler); /** * Append three routes that supports HTTP PATCH method on the same handler: * * <pre> * patch("/p1", "/p2", req {@literal ->} { * return req.path(); * }); * </pre> * * This is a singleton route so make sure you don't share or use global variables. * * @param path1 A path pattern. * @param path2 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection patch(String path1, String path2, Route.OneArgHandler handler); /** * Append three routes that supports HTTP PATCH method on the same handler: * * <pre> * patch("/p1", "/p2", "/p3", req {@literal ->} { * return req.path(); * }); * </pre> * * This is a singleton route so make sure you don't share or use global variables. * * @param path1 A path pattern. * @param path2 A path pattern. * @param path3 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection patch(String path1, String path2, String path3, Route.OneArgHandler handler); /** * Append route that supports HTTP PATCH method: * * <pre> * patch("/", () {@literal ->} { * return Results.ok(); * }); * </pre> * * This is a singleton route so make sure you don't share or use global variables. * * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition patch(String path, Route.ZeroArgHandler handler); /** * Append three routes that supports HTTP PATCH method on the same handler: * * <pre> * patch("/p1", "/p2", () {@literal ->} { * return Results.ok(); * }); * </pre> * * This is a singleton route so make sure you don't share or use global variables. * * @param path1 A path pattern. * @param path2 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection patch(String path1, String path2, Route.ZeroArgHandler handler); /** * Append three routes that supports HTTP PATCH method on the same handler: * * <pre> * patch("/p1", "/p2", "/p3", () {@literal ->} { * return Results.ok(); * }); * </pre> * * This is a singleton route so make sure you don't share or use global variables. * * @param path1 A path pattern. * @param path2 A path pattern. * @param path3 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection patch(String path1, String path2, String path3, Route.ZeroArgHandler handler); /** * Append route that supports HTTP PATCH method: * * <pre> * patch("/", (req, rsp, chain) {@literal ->} { * chain.next(req, rsp); * }); * </pre> * * @param path A path pattern. * @param filter A callback to execute. * @return A new route definition. */ Route.Definition patch(String path, Route.Filter filter); /** * Append three routes that supports HTTP PATCH method on the same handler: * * <pre> * patch("/p1", "/p2", (req, rsp, chain) {@literal ->} { * chain.next(req, rsp); * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param filter A filter to execute. * @return A new route definition. */ Route.Collection patch(String path1, String path2, Route.Filter filter); /** * Append three routes that supports HTTP PATCH method on the same handler: * * <pre> * patch("/p1", "/p2", "/p3", (req, rsp, chain) {@literal ->} { * chain.next(req, rsp); * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param path3 A path pattern. * @param filter A filter to execute. * @return A new route definition. */ Route.Collection patch(String path1, String path2, String path3, Route.Filter filter); /** * Append a route that supports HTTP DELETE method: * * <pre> * delete("/", (req, rsp) {@literal ->} { * rsp.status(204); * }); * </pre> * * This is a singleton route so make sure you don't share or use global variables. * * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition delete(String path, Route.Handler handler); /** * Append three routes that supports HTTP DELETE method on the same handler: * * <pre> * delete("/p1", "/p2", (req, rsp) {@literal ->} { * rsp.status(204); * }); * </pre> * * This is a singleton route so make sure you don't share or use global variables. * * @param path1 A path pattern. * @param path2 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection delete(String path1, String path2, Route.Handler handler); /** * Append three routes that supports HTTP DELETE method on the same handler: * * <pre> * delete("/p1", "/p2", "/p3", (req, rsp) {@literal ->} { * rsp.status(204); * }); * </pre> * * This is a singleton route so make sure you don't share or use global variables. * * @param path1 A path pattern. * @param path2 A path pattern. * @param path3 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection delete(String path1, String path2, String path3, Route.Handler handler); /** * Append route that supports HTTP DELETE method: * * <pre> * delete("/", req {@literal ->} * return Results.noContent(); * ); * </pre> * * This is a singleton route so make sure you don't share or use global variables. * * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition delete(String path, Route.OneArgHandler handler); /** * Append three routes that supports HTTP DELETE method on the same handler: * * <pre> * delete("/p1", "/p2", req {@literal ->} { * return Results.noContent(); * }); * </pre> * * This is a singleton route so make sure you don't share or use global variables. * * @param path1 A path pattern. * @param path2 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection delete(String path1, String path2, Route.OneArgHandler handler); /** * Append three routes that supports HTTP DELETE method on the same handler: * * <pre> * delete("/p1", "/p2", "/p3",req {@literal ->} { * return Results.noContent(); * }); * </pre> * * This is a singleton route so make sure you don't share or use global variables. * * @param path1 A path pattern. * @param path2 A path pattern. * @param path3 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection delete(String path1, String path2, String path3, Route.OneArgHandler handler); /** * Append route that supports HTTP DELETE method: * * <pre> * delete("/", () {@literal ->} * return Results.noContent(); * ); * </pre> * * This is a singleton route so make sure you don't share or use global variables. * * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition delete(String path, Route.ZeroArgHandler handler); /** * Append three routes that supports HTTP DELETE method on the same handler: * * <pre> * delete("/p1", "/p2", () {@literal ->} { * return Results.noContent(); * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection delete(String path1, String path2, Route.ZeroArgHandler handler); /** * Append three routes that supports HTTP DELETE method on the same handler: * * <pre> * delete("/p1", "/p2", "/p3", req {@literal ->} { * return Results.noContent(); * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param path3 A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Collection delete(String path1, String path2, String path3, Route.ZeroArgHandler handler); /** * Append a route that supports HTTP DELETE method: * * <pre> * delete("/", (req, rsp, chain) {@literal ->} { * rsp.status(304); * chain.next(req, rsp); * }); * </pre> * * @param path A path pattern. * @param filter A callback to execute. * @return A new route definition. */ Route.Definition delete(String path, Route.Filter filter); /** * Append three routes that supports HTTP DELETE method on the same handler: * * <pre> * delete("/p1", "/p2", (req, rsp, chain) {@literal ->} { * rsp.status(304); * chain.next(req, rsp); * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param filter A filter to execute. * @return A new route definition. */ Route.Collection delete(String path1, String path2, Route.Filter filter); /** * Append three routes that supports HTTP DELETE method on the same handler: * * <pre> * delete("/p1", "/p2", "/p3", (req, rsp, chain) {@literal ->} { * rsp.status(304); * chain.next(req, rsp); * }); * </pre> * * @param path1 A path pattern. * @param path2 A path pattern. * @param path3 A path pattern. * @param filter A filter to execute. * @return A new route definition. */ Route.Collection delete(String path1, String path2, String path3, Route.Filter filter); /** * Append a route that supports HTTP TRACE method: * * <pre> * trace("/", (req, rsp) {@literal ->} { * rsp.send(...); * }); * </pre> * * @param path A path pattern. * @param handler A callback to execute. * @return A new route definition. */ Route.Definition trace(String path, Route.Handler handler); /** * Append route that supports HTTP TRACE method: * * <pre> * trace("/", req {@literal ->} * "trace" * ); * </pre> * * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition trace(String path, Route.OneArgHandler handler); /** * Append route that supports HTTP TRACE method: * * <pre> * trace("/", () {@literal ->} * "trace" * ); * </pre> * * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition trace(String path, Route.ZeroArgHandler handler); /** * Append a route that supports HTTP TRACE method: * * <pre> * trace("/", (req, rsp, chain) {@literal ->} { * chain.next(req, rsp); * }); * </pre> * * @param path A path pattern. * @param filter A callback to execute. * @return A new route definition. */ Route.Definition trace(String path, Route.Filter filter); /** * Append a default trace implementation under the given path. Default trace response, looks * like: * * <pre> * TRACE /path * header1: value * header2: value * </pre> * * @return A new route definition. */ Route.Definition trace(); /** * Append a route that supports HTTP CONNECT method: * * <pre> * connect("/", (req, rsp) {@literal ->} { * }); * </pre> * * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition connect(String path, Route.Handler handler); /** * Append route that supports HTTP CONNECT method: * * <pre> * connect("/", req {@literal ->} * "hello" * ); * </pre> * * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition connect(String path, Route.OneArgHandler handler); /** * Append route that supports HTTP CONNECT method: * * <pre> * connect("/", () {@literal ->} * "connected" * ); * </pre> * * @param path A path pattern. * @param handler A handler to execute. * @return A new route definition. */ Route.Definition connect(String path, Route.ZeroArgHandler handler); /** * Append a route that supports HTTP CONNECT method: * * <pre> * connect("/", (req, rsp, chain) {@literal ->} { * chain.next(req, rsp); * }); * </pre> * * @param path A path pattern. * @param filter A filter to execute. * @return A new route definition. */ Route.Definition connect(String path, Route.Filter filter); /** * Static files handler. * * <pre> * assets("/assets/**"); * </pre> * * Resources are served from root of classpath, for example <code>GET /assets/file.js</code> will * be resolve as classpath resource at the same location. * * The {@link AssetHandler} one step forward and add support for serving files from a CDN out of * the box. All you have to do is to define a <code>assets.cdn</code> property: * * <pre> * assets.cdn = "http://d7471vfo50fqt.cloudfront.net" * </pre> * * A GET to <code>/assets/js/index.js</code> will be redirected to: * <code>http://d7471vfo50fqt.cloudfront.net/assets/js/index.js</code>. * * You can turn on/off <code>ETag</code> and <code>Last-Modified</code> headers too using * <code>assets.etag</code> and <code>assets.lastModified</code>. These two properties are enabled * by default. * * @param path The path to publish. * @return A new route definition. */ default Route.Definition assets(final String path) { return assets(path, "/"); } /** * Static files handler on external location. * * <pre> * assets("/assets/**", Paths.get("/www")); * </pre> * * For example <code>GET /assets/file.js</code> will be resolve as <code>/www/file.js</code> on * server file system. * * <p> * The {@link AssetHandler} one step forward and add support for serving files from a CDN out of * the box. All you have to do is to define a <code>assets.cdn</code> property: * </p> * <pre> * assets.cdn = "http://d7471vfo50fqt.cloudfront.net" * </pre> * * A GET to <code>/assets/js/index.js</code> will be redirected to: * <code>http://d7471vfo50fqt.cloudfront.net/assets/js/index.js</code>. * * You can turn on/off <code>ETag</code> and <code>Last-Modified</code> headers too using * <code>assets.etag</code> and <code>assets.lastModified</code>. These two properties are enabled * by default. * * @param path The path to publish. * @param basedir Base directory. * @return A new route definition. */ Route.Definition assets(final String path, Path basedir); /** * Static files handler. Like {@link #assets(String)} but let you specify a different classpath * location. * * <p> * Basic example * </p> * * <pre> * assets("/js/**", "/"); * </pre> * * A request for: <code>/js/jquery.js</code> will be translated to: <code>/lib/jquery.js</code>. * * <p> * Webjars example: * </p> * * <pre> * assets("/js/**", "/resources/webjars/{0}"); * </pre> * * A request for: <code>/js/jquery/2.1.3/jquery.js</code> will be translated to: * <code>/resources/webjars/jquery/2.1.3/jquery.js</code>. * The <code>{0}</code> represent the <code>**</code> capturing group. * * <p> * Another webjars example: * </p> * * <pre> * assets("/js/*-*.js", "/resources/webjars/{0}/{1}/{0}.js"); * </pre> * * <p> * A request for: <code>/js/jquery-2.1.3.js</code> will be translated to: * <code>/resources/webjars/jquery/2.1.3/jquery.js</code>. * </p> * * @param path The path to publish. * @param location A resource location. * @return A new route definition. */ Route.Definition assets(String path, String location); /** * Send static files, like {@link #assets(String)} but let you specify a custom * {@link AssetHandler}. * * @param path The path to publish. * @param handler Asset handler. * @return A new route definition. */ Route.Definition assets(String path, AssetHandler handler); /** * <p> * Append MVC routes from a controller like class: * </p> * * <pre> * use(MyRoute.class); * </pre> * * Where MyRoute.java is: * * <pre> * {@literal @}Path("/") * public class MyRoute { * * {@literal @}GET * public String hello() { * return "Hello Jooby"; * } * } * </pre> * <p> * Programming model is quite similar to JAX-RS/Jersey with some minor differences and/or * simplifications. * </p> * * <p> * To learn more about Mvc Routes, please check {@link org.jooby.mvc.Path}, * {@link org.jooby.mvc.Produces} {@link org.jooby.mvc.Consumes}. * </p> * * @param routeClass A route(s) class. * @return This jooby instance. */ Route.Collection use(Class<?> routeClass); /** * <h2>before</h2> * * Allows for customized handler execution chains. It will be invoked before the actual handler. * * <pre>{@code * { * before((req, rsp) -> { * // your code goes here * }); * } * }</pre> * * You are allowed to modify the request and response objects. * * Please note that the <code>before</code> handler is just syntax sugar for {@link Route.Filter}. * For example, the <code>before</code> handler was implemented as: * * <pre>{@code * { * use("*", "*", (req, rsp, chain) -> { * before(req, rsp); * // your code goes here * chain.next(req, rsp); * }); * } * }</pre> * * A <code>before</code> handler must to be registered before the actual handler you want to * intercept. * * <pre>{@code * { * before((req, rsp) -> { * // your code goes here * }); * * get("/path", req -> { * // your code goes here * return ...; * }); * } * }</pre> * * If you reverse the order then it won't work. * * <p> * <strong>Remember</strong>: routes are executed in the order they are defined and the pipeline * is executed as long you don't generate a response. * </p> * * @param handler Before handler. * @param chain Chain of before handler. * @return A new route definition. */ default Route.Collection before(final Route.Before handler, final Route.Before... chain) { return before("*", handler, chain); } /** * <h2>before</h2> * * Allows for customized handler execution chains. It will be invoked before the actual handler. * * <pre>{@code * { * before("*", (req, rsp) -> { * // your code goes here * }); * } * }</pre> * * You are allowed to modify the request and response objects. * * Please note that the <code>before</code> handler is just syntax sugar for {@link Route.Filter}. * For example, the <code>before</code> handler was implemented as: * * <pre>{@code * { * use("*", (req, rsp, chain) -> { * before(req, rsp); * chain.next(req, rsp); * }); * } * }</pre> * * A <code>before</code> handler must to be registered before the actual handler you want to * intercept. * * <pre>{@code * { * before("/path", (req, rsp) -> { * // your code goes here * }); * * get("/path", req -> { * // your code goes here * return ...; * }); * } * }</pre> * * If you reverse the order then it won't work. * * <p> * <strong>Remember</strong>: routes are executed in the order they are defined and the pipeline * is executed as long you don't generate a response. * </p> * * @param pattern Pattern to intercept. * @param handler Before handler. * @param chain Chain of before handler. * @return A new route definition. */ default Route.Collection before(final String pattern, final Route.Before handler, final Route.Before... chain) { return before("*", pattern, handler, chain); } /** * <h2>before</h2> * * Allows for customized handler execution chains. It will be invoked before the actual handler. * * <pre>{@code * { * before("GET", "*", (req, rsp) -> { * // your code goes here * }); * } * }</pre> * * You are allowed to modify the request and response objects. * * Please note that the <code>before</code> handler is just syntax sugar for {@link Route.Filter}. * For example, the <code>before</code> handler was implemented as: * * <pre>{@code * { * use("GET", "*", (req, rsp, chain) -> { * before(req, rsp); * chain.next(req, rsp); * }); * } * }</pre> * * A <code>before</code> handler must to be registered before the actual handler you want to * intercept. * * <pre>{@code * { * before("GET", "/path", (req, rsp) -> { * // your code goes here * }); * * get("/path", req -> { * // your code goes here * return ...; * }); * } * }</pre> * * If you reverse the order then it won't work. * * <p> * <strong>Remember</strong>: routes are executed in the order they are defined and the pipeline * is executed as long you don't generate a response. * </p> * * @param method HTTP method to intercept. * @param pattern Pattern to intercept. * @param handler Before handler. * @param chain Chain of before handler. * @return A new route definition. */ Route.Collection before(String method, String pattern, Route.Before handler, Route.Before... chain); /** * <h2>after</h2> * * Allows for customized response before sending it. It will be invoked at the time a response * need * to be send. * * <pre>{@code * { * after((req, rsp, result) -> { * // your code goes here * return result; * }); * } * }</pre> * * You are allowed to modify the request, response and result objects. The handler returns a * {@link Result} which can be the same or an entirely new {@link Result}. * * Please note that the <code>after</code> handler is just syntax sugar for * {@link Route.Filter}. * For example, the <code>after</code> handler was implemented as: * * <pre>{@code * { * use("*", (req, rsp, chain) -> { * chain.next(req, new Response.Forwarding(rsp) { * public void send(Result result) { * rsp.send(after(req, rsp, result); * } * }); * }); * } * }</pre> * * Due <code>after</code> is implemented by wrapping the {@link Response} object. A * <code>after</code> handler must to be registered before the actual handler you want to * intercept. * * <pre>{@code * { * after((req, rsp, result) -> { * // your code goes here * return result; * }); * * get("/path", req -> { * return "hello"; * }); * } * }</pre> * * If you reverse the order then it won't work. * * <p> * <strong>Remember</strong>: routes are executed in the order they are defined and the pipeline * is executed as long you don't generate a response. * </p> * * @param handler After handler. * @param chain After chain. * @return A new route definition. */ default Route.Collection after(final Route.After handler, final Route.After... chain) { return after("*", handler, chain); } /** * <h2>after</h2> * * Allows for customized response before sending it. It will be invoked at the time a response * need to be send. * * <pre>{@code * { * before("*", (req, rsp, result) -> { * // your code goes here * return result; * }); * } * }</pre> * * You are allowed to modify the request, response and result objects. The handler returns a * {@link Result} which can be the same or an entirely new {@link Result}. * * Please note that the <code>after</code> handler is just syntax sugar for {@link Route.Filter}. * For example, the <code>after</code> handler was implemented as: * * <pre>{@code * { * use("*", (req, rsp, chain) -> { * chain.next(req, new Response.Forwarding(rsp) { * public void send(Result result) { * rsp.send(after(req, rsp, result); * } * }); * }); * } * }</pre> * * Due <code>after</code> is implemented by wrapping the {@link Response} object. A * <code>after</code> handler must to be registered before the actual handler you want to * intercept. * * <pre>{@code * { * after("/path", (req, rsp, result) -> { * // your code goes here * return result; * }); * * get("/path", req -> { * return "hello"; * }); * } * }</pre> * * If you reverse the order then it won't work. * * <p> * <strong>Remember</strong>: routes are executed in the order they are defined and the pipeline * is executed as long you don't generate a response. * </p> * * @param pattern Pattern to intercept. * @param handler After handler. * @param chain After chain. * @return A new route definition. */ default Route.Collection after(final String pattern, final Route.After handler, final Route.After... chain) { return after("*", pattern, handler, chain); } /** * <h2>after</h2> * * Allows for customized response before sending it. It will be invoked at the time a response * need to be send. * * <pre>{@code * { * after("GET", "*", (req, rsp, result) -> { * // your code goes here * return result; * }); * } * }</pre> * * You are allowed to modify the request, response and result objects. The handler returns a * {@link Result} which can be the same or an entirely new {@link Result}. * * Please note that the <code>after</code> handler is just syntax sugar for * {@link Route.Filter}. * For example, the <code>after</code> handler was implemented as: * * <pre>{@code * { * use("GET", "*", (req, rsp, chain) -> { * chain.next(req, new Response.Forwarding(rsp) { * public void send(Result result) { * rsp.send(after(req, rsp, result); * } * }); * }); * } * }</pre> * * Due <code>after</code> is implemented by wrapping the {@link Response} object. A * <code>after</code> handler must to be registered before the actual handler you want to * intercept. * * <pre>{@code * { * after("GET", "/path", (req, rsp, result) -> { * // your code goes here * return result; * }); * * get("/path", req -> { * return "hello"; * }); * } * }</pre> * * If you reverse the order then it won't work. * * <p> * <strong>Remember</strong>: routes are executed in the order they are defined and the pipeline * is executed as long you don't generate a response. * </p> * * @param method HTTP method to intercept. * @param pattern Pattern to intercept. * @param handler After handler. * @param chain After chain. * @return A new route definition. */ Route.Collection after(String method, String pattern, Route.After handler, Route.After... chain); /** * <h2>complete</h2> * * Allows for log and cleanup a request. It will be invoked after we send a response. * * <pre>{@code * { * complete((req, rsp, cause) -> { * // your code goes here * }); * } * }</pre> * * You are NOT allowed to modify the request and response objects. The <code>cause</code> is an * {@link Optional} with a {@link Throwable} useful to identify problems. * * The goal of the <code>after</code> handler is to probably cleanup request object and log * responses. * * Please note that the <code>complete</code> handler is just syntax sugar for * {@link Route.Filter}. * For example, the <code>complete</code> handler was implemented as: * * <pre>{@code * { * use("*", "*", (req, rsp, chain) -> { * Optional<Throwable> err = Optional.empty(); * try { * chain.next(req, rsp); * } catch (Throwable cause) { * err = Optional.of(cause); * } finally { * complete(req, rsp, err); * } * }); * } * }</pre> * * An <code>complete</code> handler must to be registered before the actual handler you want to * intercept. * * <pre>{@code * { * complete((req, rsp, cause) -> { * // your code goes here * }); * * get(req -> { * return "hello"; * }); * } * }</pre> * * If you reverse the order then it won't work. * * <p> * <strong>Remember</strong>: routes are executed in the order they are defined and the pipeline * is executed as long you don't generate a response. * </p> * * <h2>example</h2> * <p> * Suppose you have a transactional resource, like a database connection. The next example shows * you how to implement a simple and effective <code>transaction-per-request</code> pattern: * </p> * * <pre>{@code * { * // start transaction * before((req, rsp) -> { * DataSource ds = req.require(DataSource.class); * Connection connection = ds.getConnection(); * Transaction trx = connection.getTransaction(); * trx.begin(); * req.set("connection", connection); * return true; * }); * * // commit/rollback transaction * complete((req, rsp, cause) -> { * // unbind connection from request * try(Connection connection = req.unset("connection").get()) { * Transaction trx = connection.getTransaction(); * if (cause.ifPresent()) { * trx.rollback(); * } else { * trx.commit(); * } * } * }); * * // your transactional routes goes here * get("/api/something", req -> { * Connection connection = req.get("connection"); * // work with connection * }); * } * }</pre> * * @param handler Complete handler. * @param chain Complete chain. * @return A new route definition. */ default Route.Collection complete(final Route.Complete handler, final Route.Complete... chain) { return complete("*", handler, chain); } /** * <h2>complete</h2> * * Allows for log and cleanup a request. It will be invoked after we send a response. * * <pre>{@code * { * complete("*", (req, rsp, cause) -> { * // your code goes here * }); * } * }</pre> * * You are NOT allowed to modify the request and response objects. The <code>cause</code> is an * {@link Optional} with a {@link Throwable} useful to identify problems. * * The goal of the <code>complete</code> handler is to probably cleanup request object and log * responses. * * Please note that the <code>complete</code> handler is just syntax sugar for * {@link Route.Filter}. * For example, the <code>complete</code> handler was implemented as: * * <pre>{@code * { * use("*", "*", (req, rsp, chain) -> { * Optional<Throwable> err = Optional.empty(); * try { * chain.next(req, rsp); * } catch (Throwable cause) { * err = Optional.of(cause); * } finally { * complete(req, rsp, err); * } * }); * } * }</pre> * * An <code>complete</code> handler must to be registered before the actual handler you want to * intercept. * * <pre>{@code * { * complete("/path", (req, rsp, cause) -> { * // your code goes here * }); * * get("/path", req -> { * return "hello"; * }); * } * }</pre> * * If you reverse the order then it won't work. * * <p> * <strong>Remember</strong>: routes are executed in the order they are defined and the pipeline * is executed as long you don't generate a response. * </p> * * <h2>example</h2> * <p> * Suppose you have a transactional resource, like a database connection. The next example shows * you how to implement a simple and effective <code>transaction-per-request</code> pattern: * </p> * * <pre>{@code * { * // start transaction * before("/api/*", (req, rsp) -> { * DataSource ds = req.require(DataSource.class); * Connection connection = ds.getConnection(); * Transaction trx = connection.getTransaction(); * trx.begin(); * req.set("connection", connection); * return true; * }); * * // commit/rollback transaction * complete("/api/*", (req, rsp, cause) -> { * // unbind connection from request * try(Connection connection = req.unset("connection").get()) { * Transaction trx = connection.getTransaction(); * if (cause.ifPresent()) { * trx.rollback(); * } else { * trx.commit(); * } * } * }); * * // your transactional routes goes here * get("/api/something", req -> { * Connection connection = req.get("connection"); * // work with connection * }); * } * }</pre> * * @param pattern Pattern to intercept. * @param handler Complete handler. * @param chain Complete chain. * @return A new route definition. */ default Route.Collection complete(final String pattern, final Route.Complete handler, final Route.Complete... chain) { return complete("*", pattern, handler, chain); } /** * <h2>after</h2> * * Allows for log and cleanup a request. It will be invoked after we send a response. * * <pre>{@code * { * complete("*", "*", (req, rsp, cause) -> { * // your code goes here * }); * } * }</pre> * * You are NOT allowed to modify the request and response objects. The <code>cause</code> is an * {@link Optional} with a {@link Throwable} useful to identify problems. * * The goal of the <code>complete</code> handler is to probably cleanup request object and log * responses. * * Please note that the <code>complete</code> handler is just syntax sugar for * {@link Route.Filter}. * For example, the <code>complete</code> handler was implemented as: * * <pre>{@code * { * use("*", "*", (req, rsp, chain) -> { * Optional<Throwable> err = Optional.empty(); * try { * chain.next(req, rsp); * } catch (Throwable cause) { * err = Optional.of(cause); * } finally { * complete(req, rsp, err); * } * }); * } * }</pre> * * An <code>complete</code> handler must to be registered before the actual handler you want to * intercept. * * <pre>{@code * { * complete("*", "/path", (req, rsp, cause) -> { * }); * * get("/path", req -> { * return "hello"; * }); * } * }</pre> * * If you reverse the order then it won't work. * * <p> * <strong>Remember</strong>: routes are executed in the order they are defined and the pipeline * is executed as long you don't generate a response. * </p> * * <h2>example</h2> * <p> * Suppose you have a transactional resource, like a database connection. The next example shows * you how to implement a simple and effective <code>transaction-per-request</code> pattern: * </p> * * <pre>{@code * { * // start transaction * before((req, rsp) -> { * DataSource ds = req.require(DataSource.class); * Connection connection = ds.getConnection(); * Transaction trx = connection.getTransaction(); * trx.begin(); * req.set("connection", connection); * return true; * }); * * // commit/rollback transaction * complete((req, rsp, cause) -> { * // unbind connection from request * try(Connection connection = req.unset("connection")) { * Transaction trx = connection.getTransaction(); * if (cause.ifPresent()) { * trx.rollback(); * } else { * trx.commit(); * } * } * }); * * // your transactional routes goes here * get("/my-trx-route", req -> { * Connection connection = req.get("connection"); * // work with connection * }); * } * }</pre> * * @param method HTTP method to intercept. * @param pattern Pattern to intercept. * @param handler Complete handler. * @param chain Complete chain. * @return A new route definition. */ Route.Collection complete(String method, String pattern, Route.Complete handler, Route.Complete... chain); /** * Append a new WebSocket handler under the given path. * * <pre> * ws("/ws", (socket) {@literal ->} { * // connected * socket.onMessage(message {@literal ->} { * System.out.println(message); * }); * socket.send("Connected"): * }); * </pre> * * @param path A path pattern. * @param handler A connect callback. * @return A new WebSocket definition. */ default WebSocket.Definition ws(final String path, final WebSocket.OnOpen1 handler) { return ws(path, (WebSocket.OnOpen) handler); } /** * Append a new WebSocket handler under the given path. * * <pre> * ws("/ws", (req, socket) {@literal ->} { * // connected * socket.onMessage(message {@literal ->} { * System.out.println(message); * }); * socket.send("Connected"): * }); * </pre> * * @param path A path pattern. * @param handler A connect callback. * @return A new WebSocket definition. */ WebSocket.Definition ws(String path, WebSocket.OnOpen handler); default <T> WebSocket.Definition ws(final Class<? extends WebSocket.OnMessage<T>> handler) { return ws("", handler); } <T> WebSocket.Definition ws(String path, Class<? extends WebSocket.OnMessage<T>> handler); /** * Add a server-sent event handler. * * <pre>{@code * { * sse("/path",(req, sse) -> { * // 1. connected * sse.send("data"); // 2. send/push data * }); * } * }</pre> * * @param path Event path. * @param handler Callback. It might executed in a different thread (web server choice). * @return A route definition. */ Route.Definition sse(String path, Sse.Handler handler); /** * Add a server-sent event handler. * * <pre>{@code * { * sse("/path", sse -> { * // 1. connected * sse.send("data"); // 2. send/push data * }); * } * }</pre> * * @param path Event path. * @param handler Callback. It might executed in a different thread (web server choice). * @return A route definition. */ Route.Definition sse(String path, Sse.Handler1 handler); /** * Apply common configuration and attributes to a group of routes: * * <pre>{@code * { * with(() -> { * get("/foo", ...); * * get("/bar", ...); * * get("/etc", ...); * * ... * }).attr("v1", "k1") * .excludes("/public/**"); * } * }</pre> * * All the routes wrapped by <code>with</code> will have a <code>v1</code> attribute and will * excludes/ignores a <code>/public</code> request. * * @param callback Route callback. * @return A route collection. */ Route.Collection with(Runnable callback); /** * Apply the mapper to all the functional routes. * * <pre>{@code * { * mapper((Integer v) -> v * 2); * * mapper(v -> Integer.parseInt(v.toString())); * * get("/four", () -> "2"); * } * }</pre> * * A call to <code>/four</code> outputs <code>4</code>. Mapper are applied in reverse order. * * @param mapper Route mapper to append. * @return This instance. */ Router map(final Mapper<?> mapper); /** * Setup a route error handler. Default error handler {@link Err.DefHandler} does content * negotation and this method allow to override/complement default handler. * * This is a catch all error handler. * * <h2>html</h2> * * If a request has an Accept: <code>text/html</code> header. Then, the default err handler will * ask to a {@link View.Engine} to render the <code>err</code> view. * * The default model has these attributes: * <pre> * message: exception string * stacktrace: exception stack-trace as an array of string * status: status code, like 400 * reason: status code reason, like BAD REQUEST * </pre> * * Here is a simply <code>public/err.html</code> error page: * * <pre> * <html> * <body> * {{ "{{status" }}}}:{{ "{{reason" }}}} * </body> * </html> * </pre> * * HTTP status code will be set too. * * @param err A route error handler. * @return This jooby instance. */ Router err(Err.Handler err); /** * Setup a custom error handler.The error handler will be executed if the current exception is an * instance of given type type. * * @param type Exception type. The error handler will be executed if the current exception is an * instance of this type. * @param handler A route error handler. * @return This jooby instance. */ default Router err(final Class<? extends Throwable> type, final Err.Handler handler) { return err((req, rsp, err) -> { Throwable cause = err.getCause(); if (type.isInstance(cause)) { handler.handle(req, rsp, err); } }); } /** * Setup a route error handler. The error handler will be executed if current status code matches * the one provided. * * @param statusCode The status code to match. * @param handler A route error handler. * @return This jooby instance. */ default Router err(final int statusCode, final Err.Handler handler) { return err((req, rsp, err) -> { if (statusCode == err.statusCode()) { handler.handle(req, rsp, err); } }); } /** * Setup a route error handler. The error handler will be executed if current status code matches * the one provided. * * @param code The status code to match. * @param handler A route error handler. * @return This jooby instance. */ default Router err(final Status code, final Err.Handler handler) { return err((req, rsp, err) -> { if (code.value() == err.statusCode()) { handler.handle(req, rsp, err); } }); } /** * Setup a route error handler. The error handler will be executed if current status code matches * the one provided. * * @param predicate Apply the error handler if the predicate evaluates to <code>true</code>. * @param handler A route error handler. * @return This jooby instance. */ default Router err(final Predicate<Status> predicate, final Err.Handler handler) { return err((req, rsp, err) -> { if (predicate.test(Status.valueOf(err.statusCode()))) { handler.handle(req, rsp, err); } }); } /** * Produces a deferred response, useful for async request processing. By default a * {@link Deferred} results run in the current thread. * * This is intentional because application code (your code) always run in a worker thread. There * is a thread pool of <code>100</code> worker threads, defined by the property: * <code>server.threads.Max</code>. * * That's why a {@link Deferred} result runs in the current thread (no need to use a new thread), * unless you want to apply a different thread model and or use a reactive/async library. * * As a final thought you might want to reduce the number of worker thread if you are going to a * build a full reactive/async application. * * <h2>usage</h2> * * <pre> * { * get("/async", promise(deferred {@literal ->} { * try { * deferred.resolve(...); // success value * } catch (Exception ex) { * deferred.reject(ex); // error value * } * })); * } * </pre> * * <p> * This method is useful for integrating reactive/async libraries. Here is an example on how to * use <a href="https://github.com/ReactiveX/RxJava">RxJava</a>: * </p> * * <pre>{@code * { * get("/rx", promise(deferred -> { * Observable.create(s -> { * s.onNext(...); * s.onCompleted(); * }).subscribeOn(Schedulers.computation()) * .subscribe(deferred::resolve, deferred::reject); * })); * } * }</pre> * * <p> * This is just an example because there is a <a href="http://jooby.org/doc/rxjava">Rx module</a>. * </p> * * <p> * Checkout the {@link #deferred(org.jooby.Route.ZeroArgHandler)} methods to see how to use a * plain {@link Executor}. * </p> * * @param initializer Deferred initializer. * @return A new deferred handler. * @see Deferred */ Route.OneArgHandler promise(Deferred.Initializer initializer); /** * Produces a deferred response, useful for async request processing. Like * {@link #promise(org.jooby.Deferred.Initializer)} but allow you to specify an {@link Executor} * to use. See {@link Jooby#executor(Executor)} and {@link Jooby#executor(String, Executor)}. * * <h2>usage</h2> * * <pre> * { * executor("forkjoin", new ForkJoinPool()); * * get("/async", promise("forkjoin", deferred {@literal ->} { * try { * deferred.resolve(...); // success value * } catch (Exception ex) { * deferred.reject(ex); // error value * } * })); * } * </pre> * * <p> * Checkout the {@link #deferred(org.jooby.Route.ZeroArgHandler)} methods to see how to use a * plain {@link Executor}. * </p> * * @param executor Executor to run the deferred. * @param initializer Deferred initializer. * @return A new deferred handler. * @see Deferred */ Route.OneArgHandler promise(String executor, Deferred.Initializer initializer); /** * Produces a deferred response, useful for async request processing. Like * {@link #promise(org.jooby.Deferred.Initializer)} but give you access to {@link Request}. * * <h2>usage</h2> * * <pre> * { * ExecutorService executor = ...; * * get("/async", promise((req, deferred) {@literal ->} { * executor.execute(() {@literal ->} { * try { * deferred.resolve(req.param("param").value()); // success value * } catch (Exception ex) { * deferred.reject(ex); // error value * } * }); * })); * } * </pre> * * @param initializer Deferred initializer. * @return A new deferred handler. * @see Deferred */ Route.OneArgHandler promise(Deferred.Initializer0 initializer); /** * Produces a deferred response, useful for async request processing. Like * {@link #promise(String, org.jooby.Deferred.Initializer)} but give you access to * {@link Request}. * * <h2>usage</h2> * * <pre> * { * get("/async", promise("myexec", (req, deferred) {@literal ->} { * // resolve a success value * deferred.resolve(req.param("param").value()); * })); * } * </pre> * * @param executor Executor to run the deferred. * @param initializer Deferred initializer. * @return A new deferred handler. * @see Deferred */ Route.OneArgHandler promise(String executor, Deferred.Initializer0 initializer); /** * Functional version of {@link #promise(org.jooby.Deferred.Initializer)}. To use ideally with one * or more {@link Executor}: * * <pre>{@code * { * executor("cached", Executors.newCachedExecutor()); * * get("/fork", deferred("cached", req -> { * return req.param("value").value(); * })); * } * }</pre> * * This handler automatically {@link Deferred#resolve(Object)} or * {@link Deferred#reject(Throwable)} a route handler response. * * @param executor Executor to run the deferred. * @param handler Application block. * @return A new deferred handler. */ default Route.ZeroArgHandler deferred(final String executor, final Route.OneArgHandler handler) { return () -> Deferred.deferred(executor, handler); } /** * Functional version of {@link #promise(org.jooby.Deferred.Initializer)}. * * Using the default executor (current thread): * * <pre>{@code * { * get("/fork", deferred(req -> { * return req.param("value").value(); * })); * } * }</pre> * * Using a custom executor: * * <pre>{@code * { * executor(new ForkJoinPool()); * * get("/fork", deferred(req -> { * return req.param("value").value(); * })); * } * }</pre> * * This handler automatically {@link Deferred#resolve(Object)} or * {@link Deferred#reject(Throwable)} a route handler response. * * @param handler Application block. * @return A new deferred handler. */ default Route.ZeroArgHandler deferred(final Route.OneArgHandler handler) { return () -> Deferred.deferred(handler); } /** * Functional version of {@link #promise(org.jooby.Deferred.Initializer)}. To use ideally with one * or more {@link Executor}: * * <pre>{@code * { * executor("cached", Executors.newCachedExecutor()); * * get("/fork", deferred("cached", () -> { * return "OK"; * })); * } * }</pre> * * This handler automatically {@link Deferred#resolve(Object)} or * {@link Deferred#reject(Throwable)} a route handler response. * * @param executor Executor to run the deferred. * @param handler Application block. * @return A new deferred handler. */ default Route.ZeroArgHandler deferred(final String executor, final Route.ZeroArgHandler handler) { return () -> Deferred.deferred(executor, handler); } /** * Functional version of {@link #promise(org.jooby.Deferred.Initializer)}. * * Using the default executor (current thread): * * <pre>{@code * { * get("/fork", deferred(() -> { * return req.param("value").value(); * })); * } * }</pre> * * Using a custom executor: * * <pre>{@code * { * executor(new ForkJoinPool()); * * get("/fork", deferred(() -> { * return req.param("value").value(); * })); * } * }</pre> * * This handler automatically {@link Deferred#resolve(Object)} or * {@link Deferred#reject(Throwable)} a route handler response. * * @param handler Application block. * @return A new deferred handler. */ default Route.ZeroArgHandler deferred(final Route.ZeroArgHandler handler) { return () -> Deferred.deferred(handler); } }