- Routing
Routing lets you use request matching criteria to bind requests to a
handlerthat implements your custom business logic. Matching criteria include one or more HTTP Method(s) and, optionally, a request path matcher. Use theRequestPredicateclass to specify more routing criteria.
Basics
Routing also supports Error Routing which binds Java Throwable to the handling logic.
Configure HTTP request routing using Routing.Builder.
Routing routing = Routing.builder()
.get("/hello", (req, res) -> res.send("Hello World!"))
.build();
WebServer webServer = WebServer.create(routing); - Handle all GETs to
/hellopath. Send theHello World!string. - Add the
routingto the WebServer.
HTTP Method Routing
Routing.Builder lets you specify how to handle each HTTP method. For example:
| HTTP Method | Routing.Builder example |
|---|---|
| GET | .get((req, res) -> { /* handler */ }) |
| PUT | .put((req, res) -> { /* handler */ }) |
| POST | .post((req, res) -> { /* handler */ }) |
| HEAD | .head((req, res) -> { /* handler */ }) |
| DELETE | .delete((req, res) -> { /* handler */ }) |
| TRACE | .trace((req, res) -> { /* handler */ }) |
| OPTIONS | .options((req, res) -> { /* handler */ }) |
| any method | .any((req, res) -> { /* handler */ }) |
| multiple methods | .anyOf(List.of(Http.Method.GET, Http.Method.POST), (req, res) -> { /* handler */ }) |
| custom method | .anyOf(Set.of(Http.RequestMethod.create("CUSTOM")), (req, res) -> { /* handler */ }) |
Path Matcher Routing
You can combine HTTP method routing with request path matching.
Routing.builder()
.post("/some/path", (req, res) -> { /* handler */ })You can use path pattern instead of path with the following syntax:
/foo/bar/baz- Exact path match against resolved path even with non-usual characters/foo/{}/baz-{}Unnamed regular expression segment([^/]+)/foo/{var}/baz- Named regular expression segment([^/]+)/foo/{var:\d+}- Named regular expression segment with a specified expression/foo/{:\d+}- Unnamed regular expression segment with a specified expression/foo/{+var}- Convenience shortcut for {var:.+}. A matcher is not a true URI template (as defined by RFC) but this convenience is in sync with the Apiary templates/foo/{+}- Convenience shortcut for unnamed segment with regular expression {:.+}/foo[/bar]- An optional block, which translates to the/foo(/bar)?regular expression/*or/foo*-*Wildcard character can be matched with any number of characters.
Path (matcher) routing is exact. For example, a /foo/bar request is not routed to .post('/foo', …).
Always start path and path patterns with the / character.
Request Predicate
Use the RequestPredicate utility class to identify more criteria. You can construct (build) a predicate based on typical request criteria such as content type, or the existence of a header or cookie. You can also construct a handler that only processes requests accepted by the predicate. All other requests are nexted, meaning that they are routed to the next valid handler.
.post("/foo",
RequestPredicate.create()
.containsHeader("my-gr8-header")
.accepts(MediaType.TEXT_PLAIN)
.and(this::isUserAuthenticated)
.thenApply((req, resp) -> {
// Some logic
})
.otherwise((req, resp) -> { /* Otherwise logic */ }); // Optional. Default logic is req.next()Organizing Code into Services
By implementing the Service interface you can organize your code into one or more services, each with its own path prefix and set of handlers.
Routing.Builder.register to register your service.register("/hello", new HelloService())public class HelloService implements Service {
@Override
public void update(Routing.Rules rules) {
rules.get("/subpath", this::getHandler);
}
private void getHandler(ServerRequest request,
ServerResponse response) {
// Some logic
}
}In this example, the GET handler matches requests to /hello/subpath.