Как открыть соединение через веб-сокет, используя собственный запрос POST с телом в качестве рукопожатия в ZIO?

Я работаю над клиент-серверным приложением Scala, используя ZIO. Мой сервер предоставляет RESTful API и должен иметь возможность обрабатывать соединения WebSocket. Я хочу реализовать что-то похожее на то, как работают kubectl и сервер Kubernetes API, где на сервер отправляется RESTful-запрос с полезной нагрузкой, включая заголовок обновления в исходном запросе для установления соединения WebSocket.

Я не могу найти документацию ZIO для этого конкретного случая или какой-либо способ вручную обрабатывать соединение через веб-сокет, например WebSocketBuilder. В настоящее время я использую стандартный способ открытия канала WebSocket с помощью ZIO:

        val httpSocket: Http[Any, Throwable, WebSocketChannelEvent, Unit] =
    Http

      // Listen for all websocket channel events
      .collectZIO[WebSocketChannelEvent] {
        ...
      }

  val app: ZIO[Any with Client with Scope, Throwable, Response] =
    httpSocket.toSocketApp.connect(url) *> ZIO.never

  val run = app.provide(zio.http.Client.default, Scope.default)

Я посмотрел на код ZClient.scala, который отвечает за обработку соединения в приведенном выше коде, и кажется, что смогу переопределитьметод, я мог бы использовать собственный запрос для открытия соединения и передать новый объект в среду приложения.

          protected override def socketInternal[R](
      app: SocketApp[R],
      headers: Headers,
      hostOption: Option[String],
      path: Path,
      portOption: Option[Int],
      queries: QueryParams,
      schemeOption: Option[Scheme],
      version: Version,
    )(implicit trace: Trace): ZIO[R with Scope, Throwable, Response] =
      for {
        env      <- ZIO.environment[R]
        location <- ZIO.fromOption {
          for {
            host   <- hostOption
            port   <- portOption
            scheme <- schemeOption
          } yield URL.Location.Absolute(scheme, host, port)
        }.orElseSucceed(URL.Location.Relative)
        res      <- requestAsync(
          Request
            .get(URL(path, location))
            .copy(
              version = version,
              headers = headers,
            ),
          clientConfig = config.copy(socketApp = Some(app.provideEnvironment(env))),
        ).withFinalizer {
          case resp: Response.CloseableResponse => resp.close.orDie
          case _                                => ZIO.unit
        }
      } yield res

Однако классявляется окончательным и использует некоторые частные классы и особенности пакета, такие как, поэтому я не могу наследовать от него.

Любое предложение о том, как подойти к этому?

0 ответов

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