4

I'm having issues with akka-http returning an exception when a akka-stream fails while being run in a akka-http complete method. Working when running the stream before akka-http returns result. Would like to stream the result even if the stream fails.

Have build a scala akka-http webserver with akka-streams running it locally in a Linux Arch OS

implicit val jsonStreamingSupport = EntityStreamingSupport.json()

  implicit def testExceptionHandler: ExceptionHandler =
    ExceptionHandler {
      case t: RuntimeException =>
        extractUri { uri =>
          log.error(s"Request to $uri could not be handled normally", t)
          complete(HttpResponse(InternalServerError, entity = s"Wups didn't work"))
        }
    }

  val innerRoute: Route = Route.seal(
    path("just-fail") {
      get {
        val marshallable = Source.single("please show me the fail").via(failingFlow).runWith(Sink.seq)
        complete(marshallable)
      }
    } ~
      path("give-me-fail") {
        get {
          complete(Source.single("please show me the fail").via(failingFlow))
        }
      }
  )

  val failingFlow: Flow[String, String, NotUsed] =
  Flow[String].map{ s =>
    throw new RuntimeException("Ka BOOOOOOOOOOOOOOOM")
  }

Want it to handle the exception this way:

% curl -v http://localhost:8080/just-fail
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /just-fail HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.63.0
> Accept: */*
> 
< HTTP/1.1 500 Internal Server Error
< Access-Control-Allow-Origin: *
< Server: akka-http/10.1.7
< Date: Wed, 06 Feb 2019 14:43:30 GMT
< Content-Type: text/plain; charset=UTF-8
< Content-Length: 16
< 
* Connection #0 to host localhost left intact
Wups didn't work%

But gets 200 OK, with "Recv failure: Connection reset by peer":

% curl -v http://localhost:8080/give-me-fail                                                                                                                                                                                                             
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /give-me-fail HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.63.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Access-Control-Allow-Origin: *
< Server: akka-http/10.1.7
< Date: Wed, 06 Feb 2019 14:46:36 GMT
< Transfer-Encoding: chunked
< Content-Type: application/json
< 
* Recv failure: Connection reset by peer
* Closing connection 0
curl: (56) Recv failure: Connection reset by peer

It seems to be against the hole purpose of connecting akka-http and akka-stream, to materialize before completing the route and returning the result.

Mads Fox
  • 61
  • 5
  • We had a similar issue: `val source = StreamConverters.fromInputStream(() => someJavaStream); ... complete(HttpResponse(entity = Chunked(ContentTypes.`application/octet-stream`, source.map(ChunkStreamPart.apply)` with a `source` whose stream is failing. It seems that akka-http simply swallows all exceptions, and there is no hook we can use to return a non-200 HTTP code when an exception happens in the stream. Our solution - use `new BufferedInputStream(someJavaStream)`, try reading a few bytes, fail with non-200 HTTP code on failures, otherwise reset the buffered stream and continue. – winitzki Sep 17 '19 at 22:19
  • @winitzki could you post a code sample of what you did with the inputstream? – Gaël J May 10 '21 at 09:22

0 Answers0