+doc,htp #19896 directives for RequestTimeout and docs

This commit is contained in:
Konrad Malawski 2016-02-26 18:38:24 +01:00
parent 27c004d274
commit 2d7d24dee6
24 changed files with 523 additions and 70 deletions

View file

@ -0,0 +1,13 @@
/*
* Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs
trait CompileOnlySpec {
/**
* Given a block of code... does NOT execute it.
* Useful when writing code samples in tests, which should only be compiled.
*/
def compileOnlySpec(body: => Unit) = ()
}

View file

@ -12,18 +12,18 @@ import akka.http.scaladsl.model._
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.{ Flow, Sink }
import akka.testkit.TestActors
import docs.CompileOnlySpec
import org.scalatest.{ Matchers, WordSpec }
import scala.language.postfixOps
import scala.concurrent.{ ExecutionContext, Future }
class HttpServerExampleSpec extends WordSpec with Matchers {
class HttpServerExampleSpec extends WordSpec with Matchers
with CompileOnlySpec {
// never actually called
val log: LoggingAdapter = null
def compileOnlySpec(body: => Unit) = ()
"binding-example" in compileOnlySpec {
import akka.http.scaladsl.Http
import akka.stream.ActorMaterializer

View file

@ -6,6 +6,9 @@ package docs.http.scaladsl.server
import akka.http.scaladsl.server.Directives
import akka.http.scaladsl.testkit.ScalatestRouteTest
import docs.CompileOnlySpec
import org.scalatest.{ Matchers, WordSpec }
abstract class RoutingSpec extends WordSpec with Matchers with Directives with ScalatestRouteTest
abstract class RoutingSpec extends WordSpec with Matchers
with Directives with ScalatestRouteTest
with CompileOnlySpec

View file

@ -260,6 +260,7 @@ class BasicDirectivesExamplesSpec extends RoutingSpec {
//#1mapResponse-advanced
trait ApiRoutes {
protected def system: ActorSystem
private val log = Logging(system, "ApiRoutes")
private val NullJsonEntity = HttpEntity(ContentTypes.`application/json`, "{}")
@ -800,5 +801,4 @@ class BasicDirectivesExamplesSpec extends RoutingSpec {
//#
}
private def compileOnlySpec(block: => Unit) = pending
}
}

View file

@ -102,5 +102,4 @@ class FileAndResourceDirectivesExamplesSpec extends RoutingSpec {
}
}
private def compileOnlySpec(block: => Unit) = pending
}

View file

@ -0,0 +1,78 @@
/*
* Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.scaladsl.server.directives
import akka.http.scaladsl.model.{ HttpResponse, StatusCodes }
import akka.http.scaladsl.server.RoutingSpec
import docs.CompileOnlySpec
import scala.concurrent.duration._
import scala.concurrent.{ Future, Promise }
class TimeoutDirectivesExamplesSpec extends RoutingSpec with CompileOnlySpec {
"Request Timeout" should {
"be configurable in routing layer" in compileOnlySpec {
//#withRequestTimeout-plain
val route =
path("timeout") {
withRequestTimeout(3.seconds) {
val response: Future[String] = slowFuture() // very slow
complete(response)
}
}
//#
}
"without timeout" in compileOnlySpec {
//#withoutRequestTimeout-1
val route =
path("timeout") {
withoutRequestTimeout {
val response: Future[String] = slowFuture() // very slow
complete(response)
}
}
//#
}
"allow mapping the response while setting the timeout" in compileOnlySpec {
//#withRequestTimeout-with-handler
val timeoutResponse = HttpResponse(StatusCodes.EnhanceYourCalm,
entity = "Unable to serve response within time limit, please enchance your calm.")
val route =
path("timeout") {
// updates timeout and handler at
withRequestTimeout(1.milli, request => timeoutResponse) {
val response: Future[String] = slowFuture() // very slow
complete(response)
}
}
//#
}
"allow mapping the response" in compileOnlySpec {
pending // compile only spec since requires actuall Http server to be run
//#withRequestTimeoutResponse
val timeoutResponse = HttpResponse(StatusCodes.EnhanceYourCalm,
entity = "Unable to serve response within time limit, please enchance your calm.")
val route =
path("timeout") {
withRequestTimeout(1.milli) {
withRequestTimeoutResponse(request => timeoutResponse) {
val response: Future[String] = slowFuture() // very slow
complete(response)
}
}
}
//#
}
}
def slowFuture(): Future[String] = Promise[String].future
}

View file

@ -65,7 +65,12 @@ Timeouts
Currently Akka HTTP doesn't implement client-side request timeout checking itself as this functionality can be regarded
as a more general purpose streaming infrastructure feature.
However, akka-stream should soon provide such a feature.
It should be noted that Akka Streams provide various timeout functionality so any API that uses a streams can benefit
from the stream stages such as ``idleTimeout``, ``completionTimeout``, ``initialTimeout`` and even ``throttle``.
To learn more about these refer to their documentation in Akka Streams (and Scala Doc).
For more details about timeout support in Akka HTTP in general refer to :ref:`http-timeouts`.
.. _http-client-layer:

View file

@ -18,4 +18,5 @@ which are specific to one side only.
unmarshalling
de-coding
json-support
xml-support
xml-support
timeouts

View file

@ -0,0 +1,76 @@
.. _http-timeouts:
Akka HTTP Timeouts
==================
Akka HTTP comes with a variety of built-in timeout mechanisms to protect your servers from malicious attacks or
programming mistakes. Some of these are simply configuration options (which may be overriden in code) while others
are left to the streaming APIs and are easily implementable as patterns in user-code directly.
Common timeouts
---------------
Idle timeouts
^^^^^^^^^^^^^
The ``idle-timeout`` is a global setting which sets the maximum inactivity time of a given connection.
In other words, if a connection is open but no request/response is being written to it for over ``idle-timeout`` time,
the connection will be automatically closed.
The setting works the same way for all connections, be it server-side or client-side, and it's configurable
independently for each of those using the following keys::
akka.http.server.idle-timeout
akka.http.client.idle-timeout
akka.http.http-connection-pool.idle-timeout
akka.http.http-connection-pool.client.idle-timeout
.. note::
For the connection pooled client side the idle period is counted only when the pool has no pending requests waiting.
Server timeouts
---------------
.. _request-timeout:
Request timeout
^^^^^^^^^^^^^^^
Request timeouts are a mechanism that limits the maximum time it may take to produce an ``HttpResponse`` from a route.
If that deadline is not met the server will automatically inject a Service Unavailable HTTP response and close the connection
to prevent it from leaking and staying around indefinitely (for example if by programming error a Future would never complete,
never sending the real response otherwise).
The default ``HttpResponse`` that is written when a request timeout is exceeded looks like this:
.. includecode2:: /../../akka-http-core/src/main/scala/akka/http/impl/engine/server/HttpServerBluePrint.scala
:snippet: default-request-timeout-httpresponse
A default request timeout is applied globally to all routes and can be configured using the
``akka.http.server.request-timeout`` setting (which defaults to 20 seconds).
.. note::
Please note that if multiple requests (``R1,R2,R3,...``) were sent by a client (see "HTTP pipelining")
using the same connection and the ``n-th`` request triggers a request timeout the server will reply with an Http Response
and close the connection, leaving the ``(n+1)-th`` (and subsequent requests on the same connection) unhandled.
The request timeout can be configured at run-time for a given route using the any of the :ref:`TimeoutDirectives`.
Bind timeout
^^^^^^^^^^^^
The bind timeout is the time period within which the TCP binding process must be completed (using any of the ``Http().bind*`` methods).
It can be configured using the ``akka.http.server.bind-timeout`` setting.
Client timeouts
---------------
Connecting timeout
^^^^^^^^^^^^^^^^^^
The connecting timeout is the time period within which the TCP connecting process must be completed.
Tweaking it should rarely be required, but it allows erroring out the connection in case a connection
is unable to be established for a given amount of time.
it can be configured using the ``akka.http.client.connecting-timeout`` setting.

View file

@ -210,10 +210,14 @@ Directive Description
:ref:`-tprovide-` Injects a given tuple of values into a directive
:ref:`-uploadedFile-` Streams one uploaded file from a multipart request to a file on disk
:ref:`-validate-` Checks a given condition before running its inner route
:ref:`-withoutRequestTimeout-` Disables :ref:`request timeouts <request-timeout>` for a given route.
:ref:`-withExecutionContext-` Runs its inner route with the given alternative ``ExecutionContext``
:ref:`-withMaterializer-` Runs its inner route with the given alternative ``Materializer``
:ref:`-withLog-` Runs its inner route with the given alternative ``LoggingAdapter``
:ref:`-withRangeSupport-` Adds ``Accept-Ranges: bytes`` to responses to GET requests, produces partial
responses if the initial request contained a valid ``Range`` header
:ref:`-withRequestTimeout-` Configures the :ref:`request timeouts <request-timeout>` for a given route.
:ref:`-withRequestTimeoutResponse-` Prepares the ``HttpResponse`` that is emitted if a request timeout is triggered.
``RequestContext => RequestContext`` function
:ref:`-withSettings-` Runs its inner route with the given alternative ``RoutingSettings``
=========================================== ============================================================================

View file

@ -74,6 +74,9 @@ Directives creating or transforming the response
:ref:`BasicDirectives` and :ref:`MiscDirectives`
Directives handling or transforming response properties.
:ref:`TimeoutDirectives`
Configure request timeouts and automatic timeout responses.
List of predefined directives by trait
--------------------------------------
@ -104,3 +107,4 @@ List of predefined directives by trait
scheme-directives/index
security-directives/index
websocket-directives/index
timeout-directives/index

View file

@ -0,0 +1,11 @@
.. _TimeoutDirectives:
TimeoutDirectives
=================
.. toctree::
:maxdepth: 1
withRequestTimeout
withoutRequestTimeout
withRequestTimeoutResponse

View file

@ -0,0 +1,49 @@
.. _-withRequestTimeout-:
withRequestTimeout
==================
Signature
---------
.. includecode2:: /../../akka-http/src/main/scala/akka/http/scaladsl/server/directives/TimeoutDirectives.scala
:snippet: withRequestTimeout
Description
-----------
This directive enables "late" (during request processing) control over the :ref:`request-timeout` feature in Akka HTTP.
The timeout can be either loosened or made more tight using this directive, however one should be aware that it is
inherently racy (which may especially show with very tight timeouts) since a timeout may already have been triggered
when this directive executes.
In case of pipelined HTTP requests (multiple requests being accepted on the same connection before sending the first response)
a the request timeout failure of the ``n-th`` request *will shut down the connection* causing the already enqueued requests
to be dropped. This is by-design, as the request timeout feature serves as a "safety net" in case of programming errors
(e.g. a Future that never completes thus potentially blocking the entire connection forever) or malicious attacks on the server.
Optionally, a timeout handler may be provided in which is called when a time-out is triggered and must produce an
``HttpResponse`` that will be sent back to the client instead of the "too late" response (in case it'd ever arrive).
See also :ref:`-withRequestTimeoutResponse-` if only looking to customise the timeout response without changing the timeout itself.
.. warning::
Please note that setting the timeout from within a directive is inherently racy (as the "point in time from which
we're measuring the timeout" is already in the past (the moment we started handling the request), so if the existing
timeout already was triggered before your directive had the chance to change it, an timeout may still be logged.
It is recommended to use a larger statically configured timeout (think of it as a "safety net" against programming errors
or malicious attackers) and if needed tighten it using the directives not the other way around.
For more information about various timeouts in Akka HTTP see :ref:`http-timeouts`.
Example
-------
.. includecode2:: ../../../../code/docs/http/scaladsl/server/directives/TimeoutDirectivesExamplesSpec.scala
:snippet: withRequestTimeout-plain
With setting the handler at the same time:
.. includecode2:: ../../../../code/docs/http/scaladsl/server/directives/TimeoutDirectivesExamplesSpec.scala
:snippet: withRequestTimeout-with-handler

View file

@ -0,0 +1,34 @@
.. _-withRequestTimeoutResponse-:
withRequestTimeoutResponse
==========================
Signature
---------
.. includecode2:: /../../akka-http/src/main/scala/akka/http/scaladsl/server/directives/TimeoutDirectives.scala
:snippet: withRequestTimeoutResponse
Description
-----------
Allows customising the ``HttpResponse`` that will be sent to clients in case of a :ref:`request-timeout`.
See also :ref:`-withRequestTimeout-` or :ref:`-withoutRequestTimeout-` if interested in dynamically changing the timeout
for a given route instead.
.. warning::
Please note that setting handler is inherently racy as the timeout is measured from starting to handle the request
to its deadline, thus if the timeout triggers before the ``withRequestTimeoutResponse`` executed it would have emitted
the default timeout HttpResponse.
In practice this can only be a problem with very tight timeouts, so with default settings
of request timeouts being measured in seconds it shouldn't be a problem in reality (though certainly a possibility still).
To learn more about various timeouts in Akka HTTP and how to configure them see :ref:`http-timeouts`.
Example
-------
.. includecode2:: ../../../../code/docs/http/scaladsl/server/directives/TimeoutDirectivesExamplesSpec.scala
:snippet: withRequestTimeoutResponse

View file

@ -0,0 +1,31 @@
.. _-withoutRequestTimeout-:
withoutRequestTimeout
=====================
Signature
---------
.. includecode2:: /../../akka-http/src/main/scala/akka/http/scaladsl/server/directives/TimeoutDirectives.scala
:snippet: withoutRequestTimeout
Description
-----------
This directive enables "late" (during request processing) control over the :ref:`request-timeout` feature in Akka HTTP.
It is not recommended to turn off request timeouts using this method as it is inherently racy and disabling request timeouts
basically turns off the safety net against programming mistakes that it provides.
.. warning::
Please note that setting the timeout from within a directive is inherently racy (as the "point in time from which
we're measuring the timeout" is already in the past (the moment we started handling the request), so if the existing
timeout already was triggered before your directive had the chance to change it, an timeout may still be logged.
For more information about various timeouts in Akka HTTP see :ref:`http-timeouts`.
Example
-------
.. includecode2:: ../../../../code/docs/http/scaladsl/server/directives/TimeoutDirectivesExamplesSpec.scala
:snippet: withoutRequestTimeout