Как обрабатывать ошибки при потоковой передаче в 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)
...

Проблема в том, что для меня это нормальный случай, когда клиент закрывает соединение. Я хочу обработать эту ошибку и просто что-нибудь записать. Как справиться с этой ошибкой?

0 ответов

Другие вопросы по тегам