+doc,htc #18600,18597 documents where/how to deal with failure in Http

This commit is contained in:
Konrad Malawski 2015-09-29 23:08:11 +02:00
parent 2f2e07666e
commit 573a69e2b9
20 changed files with 532 additions and 60 deletions

View file

@ -167,4 +167,68 @@ On the server-side the stand-alone HTTP layer forms a ``BidiFlow`` that is defin
:snippet: server-layer
You create an instance of ``Http.ServerLayer`` by calling one of the two overloads of the ``Http().serverLayer`` method,
which also allows for varying degrees of configuration.
which also allows for varying degrees of configuration.
.. _handling-http-server-failures-low-level-scala:
Handling HTTP Server failures in the Low-Level API
--------------------------------------------------
There are various situations when failure may occur while initialising or running an Akka HTTP server.
Akka by default will log all these failures, however sometimes one may want to react to failures in addition to them
just being logged, for example by shutting down the actor system, or notifying some external monitoring end-point explicitly.
There are multiple things that can fail when creating and materializing an HTTP Server (similarily, the same applied to
a plain streaming ``Tcp()`` server). The types of failures that can happen on different layers of the stack, starting
from being unable to start the server, and ending with failing to unmarshal an HttpRequest, examples of failures include
(from outer-most, to inner-most):
- Failure to ``bind`` to the specified address/port,
- Failure while accepting new ``IncommingConnection`` s, for example when the OS has run out of file descriptors or memory,
- Failure while handling a connection, for example if the incoming ``HttpRequest`` is malformed.
This section describes how to handle each failure situation, and in which situations these failures may occur.
Bind failures
^^^^^^^^^^^^^
The first type of failure is when the server is unable to bind to the given port. For example when the port
is already taken by another application, or if the port is privileged (i.e. only usable by ``root``).
In this case the "binding future" will fail immediatly, and we can react to if by listening on the Future's completion:
.. includecode2:: ../code/docs/http/scaladsl/HttpServerExampleSpec.scala
:snippet: binding-failure-handling
Once the server has successfully bound to a port, the ``Source[IncomingConnection, _]`` starts running and emiting
new incoming connections. This source technically can signal a failure as well, however this should only happen in very
dramantic situations such as running out of file descriptors or memory available to the system, such that it's not able
to accept a new incoming connection. Handling failures in Akka Streams is pretty stright forward, as failures are signaled
through the stream starting from the stage which failed, all the way downstream to the final stages.
Connections Source failures
^^^^^^^^^^^^^^^^^^^^^^^^^^^
In the example below we add a custom ``PushStage`` (see :ref:`stream-customize-scala`) in order to react to the
stream's failure. We signal a ``failureMonitor`` actor with the cause why the stream is going down, and let the Actor
handle the rest maybe it'll decide to restart the server or shutdown the ActorSystem, that however is not our concern anymore.
.. includecode2:: ../code/docs/http/scaladsl/HttpServerExampleSpec.scala
:snippet: incoming-connections-source-failure-handling
Connection failures
^^^^^^^^^^^^^^^^^^^
The third type of failure that can occur is when the connection has been properly established,
however afterwards is terminated abruptly for example by the client aborting the underlying TCP connection.
To handle this failure we can use the same pattern as in the previous snippet, however apply it to the connection's Flow:
.. includecode2:: ../code/docs/http/scaladsl/HttpServerExampleSpec.scala
:snippet: connection-stream-failure-handling
These failures can be described more or less infrastructure related, they are failing bindings or connections.
Most of the time you won't need to dive into those very deeply, as Akka will simply log errors of this kind
anyway, which is a reasonable default for such problems.
In order to learn more about handling exceptions in the actual routing layer, which is where your application code
comes into the picture, refer to :ref:`exception-handling-scala` which focuses explicitly on explaining how exceptions
thrown in routes can be handled and transformed into :class:`HttpResponse` s with apropriate error codes and human-readable failure descriptions.

View file

@ -17,7 +17,7 @@ Description
Using this directive is an alternative to using a global implicitly defined ``ExceptionHandler`` that
applies to the complete route.
See :ref:`Exception Handling` for general information about options for handling exceptions.
See :ref:`exception-handling-scala` for general information about options for handling exceptions.
Example
-------

View file

@ -4,7 +4,7 @@ failWith
========
Bubbles up the given error through the route structure where it is dealt with by the closest ``handleExceptions``
directive and its ``ExceptionHandler``.
directive and its :class:`ExceptionHandler`.
Signature
@ -19,12 +19,12 @@ Description
``failWith`` explicitly raises an exception that gets bubbled up through the route structure to be picked up by the
nearest ``handleExceptions`` directive. Using ``failWith`` rather than simply throwing an exception enables the route
structure's :ref:`Exception Handling` mechanism to deal with the exception even if the current route is executed
structure's :ref:`exception-handling-scala` mechanism to deal with the exception even if the current route is executed
asynchronously on another thread (e.g. in a ``Future`` or separate actor).
If no ``handleExceptions`` is present above the respective location in the
route structure the top-level routing logic will handle the exception and translate it into a corresponding
``HttpResponse`` using the in-scope ``ExceptionHandler`` (see also the :ref:`Exception Handling` chapter).
``HttpResponse`` using the in-scope ``ExceptionHandler`` (see also the :ref:`exception-handling-scala` chapter).
There is one notable special case: If the given exception is a ``RejectionError`` exception it is *not* bubbled up,
but rather the wrapped exception is unpacked and "executed". This allows the "tunneling" of a rejection via an

View file

@ -1,4 +1,4 @@
.. _Exception Handling:
.. _exception-handling-scala:
Exception Handling
==================

View file

@ -43,4 +43,34 @@ not really do anything useful but its definition should give you a feel for what
the Routing DSL will look like:
.. includecode2:: ../../code/docs/http/scaladsl/HttpServerExampleSpec.scala
:snippet: long-routing-example
:snippet: long-routing-example
.. _handling-http-server-failures-high-level-scala:
Handling HTTP Server failures in the High-Level API
---------------------------------------------------
There are various situations when failure may occur while initialising or running an Akka HTTP server.
Akka by default will log all these failures, however sometimes one may want to react to failures in addition
to them just being logged, for example by shutting down the actor system, or notifying some external monitoring
end-point explicitly.
Bind failures
^^^^^^^^^^^^^
For example the server might be unable to bind to the given port. For example when the port
is already taken by another application, or if the port is privileged (i.e. only usable by ``root``).
In this case the "binding future" will fail immediatly, and we can react to if by listening on the Future's completion:
.. includecode2:: ../../code/docs/http/scaladsl/HttpServerExampleSpec.scala
:snippet: binding-failure-high-level-example
.. note::
For a more low-level overview of the kinds of failures that can happen and also more fine-grained control over them
refer to the :ref:`handling-http-server-failures-low-level-scala` documentation.
Failures and exceptions inside the Routing DSL
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Exception handling within the Routing DSL is done by providing :class:`ExceptionHandler` s which are documented in-depth
in the :ref:`exception-handling-scala` section of the documtnation. You can use them to transform exceptions into
:class:`HttpResponse` s with apropriate error codes and human-readable failure descriptions.

View file

@ -14,7 +14,7 @@ Generally when a route receives a request (or rather a ``RequestContext`` for it
- Complete the request by returning the value of ``requestContext.complete(...)``
- Reject the request by returning the value of ``requestContext.reject(...)`` (see :ref:`Rejections`)
- Fail the request by returning the value of ``requestContext.fail(...)`` or by just throwing an exception (see :ref:`Exception Handling`)
- Fail the request by returning the value of ``requestContext.fail(...)`` or by just throwing an exception (see :ref:`exception-handling-scala`)
- Do any kind of asynchronous processing and instantly return a ``Future[RouteResult]`` to be eventually completed later
The first case is pretty clear, by calling ``complete`` a given response is sent to the client as reaction to the