pekko/akka-docs/rst/java/http/routing-dsl/routes.rst
Roland Kuhn 4c72495581 #19440 replace Scala Future usage with CompletionStage in javadsl
This entails:

  * adding akka.pattern.PatternCS.* to enable ask etc. with
    CompletionStage
  * changing RequestContext to offer an ExecutionContextExecutor for the
    CompletionStage.*Async combinators
  * splitting up akka.stream.Queue for JavaDSL consistency
2016-01-23 18:00:11 +01:00

90 lines
3.8 KiB
ReStructuredText

.. _routes-java:
Routes
======
A ``Route`` itself is a function that operates on a ``RequestContext`` and returns a ``RouteResult``. The
``RequestContext`` is a data structure that contains the current request and auxiliary data like the so far unmatched
path of the request URI that gets passed through the route structure. It also contains the current ``ExecutionContext``
and ``akka.stream.Materializer``, so that these don't have to be passed around manually.
.. _request-context-java:
RequestContext
--------------
The ``RequestContext`` achieves two goals: it allows access to request data and it is a factory for creating a
``RouteResult``. A user-defined handler (see :ref:`handlers-java`) that is usually used at the leaf position of
the route tree receives a ``RequestContext``, evaluates its content and then returns a result generated by one of
the methods of the context.
.. _route-result-java:
RouteResult
-----------
The ``RouteResult`` is an opaque structure that represents possible results of evaluating a route. A ``RouteResult``
can only be created by using one of the methods of the ``RequestContext``. A result can either be a response, if
it was generated by one of the ``completeX`` methods, it can be an eventual result, i.e. a ``CompletionStage<RouteResult`` if
``completeWith`` was used or a rejection that contains information about why the route could not handle the request.
Composing Routes
----------------
Routes are composed to form the route tree in two principle ways.
A route can be wrapped by a "Directive" which adds some behavioral aspect to its wrapped "inner route". Such an aspect can
be
* filtering requests to decide which requests will get to the inner route
* transforming the request before passing it to the inner route
* transforming the response (or more generally the route result) received from the inner route
* applying side-effects around inner route processing, such as measuring the time taken to run the inner route
akka-http defines a library of predefined :ref:`directives-java` and routes for all the various aspects of dealing with
HTTP requests and responses.
The other way of composition is defining a list of ``Route`` alternatives. Alternative routes are tried one after
the other until one route "accepts" the request and provides a response. Otherwise, a route can also "reject" a request,
in which case further alternatives are explored. Alternatives are specified by passing a list of routes either
to ``Directive.route()`` as in ``path("xyz").route()`` or to directives that directly take a variable number
of inner routes as argument like ``get()``.
.. _The Routing Tree-java:
The Routing Tree
----------------
Essentially, when you combine routes via nesting and alternative, you build a routing
structure that forms a tree. When a request comes in it is injected into this tree at the root and flows down through
all the branches in a depth-first manner until either some node completes it or it is fully rejected.
Consider this schematic example::
val route =
a.route(
b.route(
c.route(
... // route 1
),
d.route(
... // route 2
),
... // route 3
),
e.route(
... // route 4
)
)
Here five directives form a routing tree.
- Route 1 will only be reached if directives ``a``, ``b`` and ``c`` all let the request pass through.
- Route 2 will run if ``a`` and ``b`` pass, ``c`` rejects and ``d`` passes.
- Route 3 will run if ``a`` and ``b`` pass, but ``c`` and ``d`` reject.
Route 3 can therefore be seen as a "catch-all" route that only kicks in, if routes chained into preceding positions
reject. This mechanism can make complex filtering logic quite easy to implement: simply put the most
specific cases up front and the most general cases in the back.