diff --git a/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/TimeoutDirectivesExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/TimeoutDirectivesExamplesSpec.scala index 415219fb77..49684d2c8b 100644 --- a/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/TimeoutDirectivesExamplesSpec.scala +++ b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/TimeoutDirectivesExamplesSpec.scala @@ -25,9 +25,7 @@ private[this] object TimeoutDirectivesTestConfig { akka.stdout-loglevel = ERROR windows-connection-abort-workaround-enabled = auto akka.log-dead-letters = OFF - akka.http.server.request-timeout = 1000s""") - // large timeout - 1000s (please note - setting to infinite will disable Timeout-Access header - // and withRequestTimeout will not work) + akka.http.server.request-timeout = infinite""") } class TimeoutDirectivesExamplesSpec extends AkkaSpec(TimeoutDirectivesTestConfig.testConf) @@ -36,7 +34,7 @@ class TimeoutDirectivesExamplesSpec extends AkkaSpec(TimeoutDirectivesTestConfig import system.dispatcher implicit val materializer = ActorMaterializer() - def slowFuture(): Future[String] = Promise[String].future // move to Future.never in Scala 2.12 + def slowFuture(): Future[String] = Promise[String].future // TODO: move to Future.never in Scala 2.12 def runRoute(route: Route, routePath: String): HttpResponse = { val (_, hostname, port) = TestUtils.temporaryServerHostnameAndPort() diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/server/HttpServerBluePrint.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/server/HttpServerBluePrint.scala index 38d6a8b688..97613c2b1c 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/server/HttpServerBluePrint.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/server/HttpServerBluePrint.scala @@ -85,10 +85,7 @@ private[http] object HttpServerBluePrint { BidiFlow.fromFlows(Flow[HttpResponse], new PrepareRequests(settings)) def requestTimeoutSupport(timeout: Duration): BidiFlow[HttpResponse, HttpResponse, HttpRequest, HttpRequest, NotUsed] = - timeout match { - case x: FiniteDuration ⇒ BidiFlow.fromGraph(new RequestTimeoutSupport(x)).reversed - case _ ⇒ BidiFlow.identity - } + BidiFlow.fromGraph(new RequestTimeoutSupport(timeout)).reversed /** * Two state stage, either transforms an incoming RequestOutput into a HttpRequest with strict entity and then pushes @@ -249,7 +246,7 @@ private[http] object HttpServerBluePrint { .via(MapError[ResponseRenderingOutput](errorHandler).named("errorLogger")) } - class RequestTimeoutSupport(initialTimeout: FiniteDuration) + class RequestTimeoutSupport(initialTimeout: Duration) extends GraphStage[BidiShape[HttpRequest, HttpRequest, HttpResponse, HttpResponse]] { private val requestIn = Inlet[HttpRequest]("requestIn") private val requestOut = Outlet[HttpRequest]("requestOut") @@ -307,13 +304,21 @@ private[http] object HttpServerBluePrint { val timeout: Duration, val handler: HttpRequest ⇒ HttpResponse) - private class TimeoutAccessImpl(request: HttpRequest, initialTimeout: FiniteDuration, requestEnd: Future[Unit], + private class TimeoutAccessImpl(request: HttpRequest, initialTimeout: Duration, requestEnd: Future[Unit], trigger: AsyncCallback[(TimeoutAccess, HttpResponse)], materializer: Materializer) extends AtomicReference[Future[TimeoutSetup]] with TimeoutAccess with (HttpRequest ⇒ HttpResponse) { self ⇒ import materializer.executionContext - set { - requestEnd.fast.map(_ ⇒ new TimeoutSetup(Deadline.now, schedule(initialTimeout, this), initialTimeout, this)) + initialTimeout match { + case timeout: FiniteDuration ⇒ set { + requestEnd.fast.map(_ ⇒ new TimeoutSetup(Deadline.now, schedule(timeout, this), timeout, this)) + } + case _ ⇒ set { + requestEnd.fast.map(_ ⇒ new TimeoutSetup(Deadline.now, new Cancellable { + override def isCancelled: Boolean = true + override def cancel(): Boolean = true + }, Duration.Inf, this)) + } } override def apply(request: HttpRequest) =