Как обрабатывать ошибки при потоковой передаче в http4s
У меня есть пример потоковой передачи с
http4s
и
tapir
import java.nio.charset.StandardCharsets
import cats.effect._
import cats.implicits._
import org.http4s.HttpRoutes
import org.http4s.server.Router
import org.http4s.server.blaze.BlazeServerBuilder
import org.http4s.syntax.kleisli._
import sttp.tapir._
import sttp.tapir.server.http4s._
import fs2._
import sttp.model.HeaderNames
import scala.concurrent.ExecutionContext
import scala.concurrent.duration._
object StreamingHttp4sFs2Server extends App {
val streamingEndpoint = endpoint.get
.in("receive")
.out(header[Long](HeaderNames.ContentLength))
.out(streamBody[Stream[IO, Byte]](schemaFor[String], CodecFormat.TextPlain(), Some(StandardCharsets.UTF_8)))
// mandatory implicits
implicit val ec: ExecutionContext = scala.concurrent.ExecutionContext.Implicits.global
implicit val contextShift: ContextShift[IO] = IO.contextShift(ec)
implicit val timer: Timer[IO] = IO.timer(ec)
// converting an endpoint to a route (providing server-side logic); extension method comes from imported packages
val streamingRoutes: HttpRoutes[IO] = streamingEndpoint.toRoutes { _ =>
val size = 100L
Stream
.emit(List[Char]('a', 'b', 'c', 'd'))
.repeat
.flatMap(list => Stream.chunk(Chunk.seq(list)))
.metered[IO](100.millis)
.take(size)
.covary[IO]
.map(_.toByte)
.pure[IO]
.map(s => Right((size, s)))
}
// starting the server
BlazeServerBuilder[IO](ec)
.bindHttp(8080, "localhost")
.withHttpApp(Router("/" -> streamingRoutes).orNotFound)
.serve
.compile
.drain
.unsafeRunAsyncAndForget()
}
И протестируем это с помощью curl:
curl --no-buffer -X GET http://localhost:8080/receive
Когда я ударил
ctrl
+c
соединение разрывается. И возникает ошибка:
ERROR o.h.s.blaze.Http1ServerStage$$anon$1 - Error writing body
java.io.IOException: Обрыв канала
at java.base/sun.nio.ch.FileDispatcherImpl.write0(Native Method)
at java.base/sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:47)
at java.base/sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:113)
at java.base/sun.nio.ch.IOUtil.write(IOUtil.java:58)
at java.base/sun.nio.ch.IOUtil.write(IOUtil.java:50)
at java.base/sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:466)
at org.http4s.blaze.channel.nio1.NIO1HeadStage$.writeLoop$1(NIO1HeadStage.scala:83)
at org.http4s.blaze.channel.nio1.NIO1HeadStage$.org$http4s$blaze$channel$nio1$NIO1HeadStage$$performWrite(NIO1HeadStage.scala:98)
at org.http4s.blaze.channel.nio1.NIO1HeadStage$$anon$2.run(NIO1HeadStage.scala:244)
at org.http4s.blaze.channel.nio1.SelectorLoop$LoopRunnable.run(SelectorLoop.scala:57)
...
Проблема в том, что для меня это нормальный случай, когда клиент закрывает соединение. Я хочу обработать эту ошибку и просто что-нибудь записать. Как справиться с этой ошибкой?