=doc add lots of documentation about java-side routing API, some detail and further examples still missing
This commit is contained in:
parent
11d98a6593
commit
ab38c36cba
20 changed files with 384 additions and 50 deletions
|
|
@ -2,3 +2,7 @@
|
|||
|
||||
Connection-Level Client-Side API
|
||||
================================
|
||||
|
||||
TODO
|
||||
|
||||
For the time being, :ref:`see the Scala chapter on the same topic <ConnectionLevelApi>`.
|
||||
|
|
@ -2,3 +2,7 @@
|
|||
|
||||
Host-Level Client-Side API
|
||||
==========================
|
||||
|
||||
TODO
|
||||
|
||||
For the time being, :ref:`see the Scala chapter on the same topic <HostLevelApi>`.
|
||||
|
|
@ -2,3 +2,7 @@
|
|||
|
||||
Client-Side HTTPS Support
|
||||
=========================
|
||||
|
||||
TODO
|
||||
|
||||
For the time being, :ref:`see the Scala chapter on the same topic <clientSideHTTPS>`.
|
||||
|
|
@ -3,4 +3,6 @@
|
|||
Request-Level Client-Side API
|
||||
=============================
|
||||
|
||||
...
|
||||
TODO
|
||||
|
||||
For the time being, :ref:`see the Scala chapter on the same topic <RequestLevelApi>`.
|
||||
|
|
@ -1,4 +1,8 @@
|
|||
.. _client-side-websocket-support-java:
|
||||
|
||||
Client-Side WebSocket Support
|
||||
=============================
|
||||
|
||||
TODO
|
||||
Not yet implemented see 17275_.
|
||||
|
||||
.. _17275: https://github.com/akka/akka/issues/17275
|
||||
|
|
@ -9,6 +9,7 @@ Akka HTTP
|
|||
introduction
|
||||
configuration
|
||||
http-model
|
||||
low-level-server-side-api
|
||||
server-side/low-level-server-side-api
|
||||
server-side/websocket-support
|
||||
routing-dsl/index
|
||||
client-side/index
|
||||
|
|
@ -8,7 +8,7 @@ with a browser is of course also in scope it is not the primary focus of Akka HT
|
|||
Akka HTTP follows a rather open design and many times offers several different API levels for "doing the same thing".
|
||||
You get to pick the API level of abstraction that is most suitable for your application.
|
||||
This means that, if you have trouble achieving something using a high-level API, there's a good chance that you can get
|
||||
it done with a low-level API, which offers more flexibility but might require you do write more application code.
|
||||
it done with a low-level API, which offers more flexibility but might require you to write more application code.
|
||||
|
||||
Akka HTTP is structured into several modules:
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
.. _directives-java:
|
||||
|
||||
Directives
|
||||
==========
|
||||
|
||||
TODO
|
||||
|
|
@ -8,4 +8,7 @@ High-level Server-Side API
|
|||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
overview
|
||||
overview
|
||||
routes
|
||||
directives/index
|
||||
request-vals/index
|
||||
|
|
|
|||
|
|
@ -1,4 +1,65 @@
|
|||
.. _routing-java:
|
||||
|
||||
Routing DSL Overview
|
||||
====================
|
||||
|
||||
...
|
||||
The Akka HTTP :ref:`http-low-level-server-side-api-java` provides a ``Flow``- or ``Function``-level interface that allows
|
||||
an application to respond to incoming HTTP requests by simply mapping requests to responses
|
||||
(excerpt from :ref:`Low-level server side example <http-low-level-server-side-example-java>`):
|
||||
|
||||
.. includecode:: ../../code/docs/http/javadsl/HttpServerExampleSpec.java
|
||||
:include: request-handler
|
||||
|
||||
While it'd be perfectly possible to define a complete REST API service purely by inspecting the incoming
|
||||
``HttpRequest`` this approach becomes somewhat unwieldy for larger services due to the amount of syntax "ceremony"
|
||||
required. Also, it doesn't help in keeping your service definition as DRY_ as you might like.
|
||||
|
||||
As an alternative Akka HTTP provides a flexible DSL for expressing your service behavior as a structure of
|
||||
composable elements (called :ref:`directives-java`) in a concise and readable way. Directives are assembled into a so called
|
||||
*route structure* which, at its top-level, can be used to create a handler ``Flow`` (or, alternatively, an
|
||||
async handler function) that can be directly supplied to a ``bind`` call.
|
||||
|
||||
Here's the complete example rewritten using the composable high-level API:
|
||||
|
||||
.. includecode:: ../../code/docs/http/javadsl/HighLevelServerExample.java
|
||||
:include: high-level-server-example
|
||||
|
||||
Heart of the high-level architecture is the route tree. It is a big expression of type ``Route``
|
||||
that is evaluated only once during startup time of your service. It completely describes how your service
|
||||
should react to any request.
|
||||
|
||||
The type ``Route`` is the basic building block of the route tree. It defines if and a how a request should
|
||||
be handled. Routes are composed to form the route tree in the following two ways.
|
||||
|
||||
A route can be wrapped by a "Directive" which adds some behavioral aspect to its wrapped "inner route". ``path("ping")`` is such
|
||||
a directive that implements a path filter, i.e. it only passes control to its inner route when the unmatched path
|
||||
matches ``"ping"``. Directives can be more versatile than this: A directive can also transform the request before
|
||||
passing it into its inner route or transform a response that comes out of its inner route. It's a general and powerful
|
||||
abstraction that allows to package any kind of HTTP processing into well-defined blocks that can be freely combined.
|
||||
akka-http defines a library of predefined directives and routes for all the various aspects of dealing with
|
||||
HTTP requests and responses.
|
||||
|
||||
Read more about :ref:`directives-java`.
|
||||
|
||||
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 ``pathSingleSlash().route()`` or to directives that directly take a variable number
|
||||
of inner routes as argument like ``get()`` here.
|
||||
|
||||
Read more about :ref:`routes-java`.
|
||||
|
||||
Another important building block is a ``RequestVal<T>``. It represents a value that can be extracted from a
|
||||
request (like the URI parameter ``Parameters.stringValue("name")`` in the example) and which is then interpreted
|
||||
as a value of type ``T``. Examples of HTTP aspects represented by a ``RequestVal`` are URI parameters, HTTP form
|
||||
fields, details of the request like headers, URI, the entity, or authentication data.
|
||||
|
||||
Read more about :ref:`request-vals-java`.
|
||||
|
||||
Requests or responses often contain data that needs to be interpreted or rendered in some way.
|
||||
Akka-http provides the abstraction of ``Marshaller`` and ``Unmarshaller`` that define how domain model objects map
|
||||
to HTTP entities.
|
||||
|
||||
Read more about :ref:`marshalling-java`.
|
||||
|
||||
.. _DRY: http://en.wikipedia.org/wiki/Don%27t_repeat_yourself
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
.. _request-vals-java:
|
||||
|
||||
Request values
|
||||
==============
|
||||
|
||||
A request value of type ``RequestVal<T>`` is a typed structure that represents some aspect of the request
|
||||
that can be interpreted as a value of type ``T``. A ``RequestVal`` instance abstracts the knowledge about how
|
||||
to extract a certain value from the request and interpret it as a ``T``. It is used in combination with
|
||||
:ref:`handlers-java`.
|
||||
|
||||
The advantage of representing a request detail as a ``RequestVal`` instead of performing ad-hoc analysis of
|
||||
a request are:
|
||||
|
||||
* you can define an "inventory" of HTTP primitives for your application that you can reuse in many places of your
|
||||
application
|
||||
* automatic handling of errors when an expected value was not found in a request or if it could not be interpreted
|
||||
as the expected Java type
|
||||
|
||||
Note, that the Scala version of the routing DSL has no direct correspondent to RequestVals. Instead,
|
||||
a Scala-side ``Directive`` can have "extractions" that are reflected in the type of the ``Directive``.
|
||||
|
||||
Predefined Request values
|
||||
-------------------------
|
||||
|
||||
akka-http provides a set of predefined request values for request data commonly accessed in a web
|
||||
service.
|
||||
|
||||
These request values are defined:
|
||||
|
||||
* in ``RequestVals``: request values for basic data like URI components, request method, peer address, or the entity data
|
||||
* in ``Cookies``: request values representing cookies
|
||||
* in ``FormFields``: request values to access form fields unmarshalled to various primitive Java types
|
||||
* in ``Headers``:: request values to access request headers or header values
|
||||
* ``HttpBasicAuthenticator``: an abstract class to implement to create a request value representing a HTTP basic authenticated principal
|
||||
* in ``Parameters``: request values to access URI paramaters unmarshalled to various primitive Java types
|
||||
* in ``PathMatchers``: request values to match and access URI path segments
|
||||
* ``CustomRequestVal``: an abstract class to implement arbitrary custom request values
|
||||
90
akka-docs-dev/rst/java/http/routing-dsl/routes.rst
Normal file
90
akka-docs-dev/rst/java/http/routing-dsl/routes.rst
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
.. _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 ``Future<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.
|
||||
|
|
@ -62,7 +62,7 @@ Starting and Stopping
|
|||
On the most basic level an Akka HTTP server is bound by invoking the ``bind`` method of the `akka.http.javadsl.Http`_
|
||||
extension:
|
||||
|
||||
.. includecode:: ../code/docs/http/javadsl/HttpServerExampleSpec.java
|
||||
.. includecode:: ../../code/docs/http/javadsl/HttpServerExampleSpec.java
|
||||
:include: binding-example
|
||||
|
||||
Arguments to the ``Http().bind`` method specify the interface and port to bind to and register interest in handling
|
||||
|
|
@ -82,6 +82,7 @@ useful for example when binding to port zero (and thus letting the OS pick an av
|
|||
|
||||
.. _akka.http.javadsl.Http: @github@/akka-http-core/src/main/scala/akka/http/javadsl/Http.scala
|
||||
|
||||
.. _http-low-level-server-side-example-java:
|
||||
|
||||
Request-Response Cycle
|
||||
----------------------
|
||||
|
|
@ -98,7 +99,7 @@ Requests are handled by calling one of the ``handleWithXXX`` methods with a hand
|
|||
|
||||
Here is a complete example:
|
||||
|
||||
.. includecode:: ../code/docs/http/javadsl/HttpServerExampleSpec.java
|
||||
.. includecode:: ../../code/docs/http/javadsl/HttpServerExampleSpec.java
|
||||
:include: full-server-example
|
||||
|
||||
In this example, a request is handled by transforming the request stream with a function ``Function<HttpRequest, HttpResponse>``
|
||||
|
|
@ -111,6 +112,7 @@ if HTTP pipelining is enabled where processing of multiple incoming requests may
|
|||
``handleWithSyncHandler`` or ``handleWithAsyncHandler``, or the ``map`` or ``mapAsync`` stream operators, this
|
||||
requirement will be automatically fulfilled.
|
||||
|
||||
See :ref:`routing-java` for a more convenient high-level DSL to create request handlers.
|
||||
|
||||
Streaming Request/Response Entities
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
.. _server-side-websocket-support-java:
|
||||
|
||||
Server-Side WebSocket Support
|
||||
=============================
|
||||
|
||||
TODO
|
||||
|
||||
For the time being, :ref:`see the Scala chapter on the same topic <server-side-websocket-support-scala>`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue