Merge pull request #19871 from ktoso/wip-timeout-http-error-ktoso

=htc #19827 avoid double-push when request timeout triggers
This commit is contained in:
Konrad Malawski 2016-03-08 19:29:35 +01:00
commit ac1888fd66
25 changed files with 595 additions and 71 deletions

View file

@ -23,6 +23,7 @@ trait Directives extends RouteConcatenation
with MethodDirectives
with MiscDirectives
with ParameterDirectives
with TimeoutDirectives
with PathDirectives
with RangeDirectives
with RespondWithDirectives

View file

@ -0,0 +1,79 @@
/*
* Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package akka.http.scaladsl.server.directives
import akka.http.scaladsl.model._
import akka.http.scaladsl.model.headers.`Timeout-Access`
import akka.http.scaladsl.server.{ Directive, Directive0 }
import scala.concurrent.duration.Duration
trait TimeoutDirectives {
def withoutRequestTimeout: Directive0 =
withRequestTimeout(Duration.Inf)
/**
* Tries to set a new request timeout and handler (if provided) at the same time.
*
* Due to the inherent raciness it is not guaranteed that the update will be applied before
* the previously set timeout has expired!
*/
def withRequestTimeout(timeout: Duration): Directive0 =
withRequestTimeout(timeout, None)
/**
* Tries to set a new request timeout and handler (if provided) at the same time.
*
* Due to the inherent raciness it is not guaranteed that the update will be applied before
* the previously set timeout has expired!
*
* @param handler optional custom "timeout response" function. If left None, the default timeout HttpResponse will be used.
*/
def withRequestTimeout(timeout: Duration, handler: HttpRequest HttpResponse): Directive0 =
withRequestTimeout(timeout, Some(handler))
/**
* Tries to set a new request timeout and handler (if provided) at the same time.
*
* Due to the inherent raciness it is not guaranteed that the update will be applied before
* the previously set timeout has expired!
*
* @param handler optional custom "timeout response" function. If left None, the default timeout HttpResponse will be used.
*/
def withRequestTimeout(timeout: Duration, handler: Option[HttpRequest HttpResponse]): Directive0 =
Directive { inner
ctx
ctx.request.header[`Timeout-Access`] match {
case Some(t)
handler match {
case Some(h) t.timeoutAccess.update(timeout, h)
case _ t.timeoutAccess.updateTimeout(timeout)
}
case _ ctx.log.warning("withRequestTimeout was used in route however no request-timeout is set!")
}
inner()(ctx)
}
/**
* Tries to set a new request timeout handler, which produces the timeout response for a
* given request. Note that the handler must produce the response synchronously and shouldn't block!
*
* Due to the inherent raciness it is not guaranteed that the update will be applied before
* the previously set timeout has expired!
*/
def withRequestTimeoutResponse(handler: HttpRequest HttpResponse): Directive0 =
Directive { inner
ctx
ctx.request.header[`Timeout-Access`] match {
case Some(t) t.timeoutAccess.updateHandler(handler)
case _ ctx.log.warning("withRequestTimeoutResponse was used in route however no request-timeout is set!")
}
inner()(ctx)
}
}
object TimeoutDirectives extends TimeoutDirectives