Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to http4s 1.0 milestone #533

Open
wants to merge 1 commit into
base: experimental/http4s-ember
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
472 changes: 14 additions & 458 deletions build.sbt

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import izumi.idealingua.runtime.rpc.http4s.ws.*
import logstage.LogIO2
import org.http4s.*
import org.http4s.dsl.Http4sDsl
import org.http4s.server.websocket.WebSocketBuilder2
import org.http4s.server.websocket.WebSocketBuilder
import org.http4s.websocket.WebSocketFrame
import org.typelevel.ci.CIString
import org.typelevel.vault.Key
Expand Down Expand Up @@ -46,20 +46,20 @@ class HttpServer[F[+_, +_]: IO2: Temporal2: Primitives2: UnsafeRun2, AuthCtx](
protected val wsHeartbeatTimeout: FiniteDuration = 1.minute
protected val wsHeartbeatInterval: FiniteDuration = 10.seconds

def service(ws: WebSocketBuilder2[F[Throwable, _]]): HttpRoutes[F[Throwable, _]] = {
def service(ws: WebSocketBuilder[F[Throwable, _]]): HttpRoutes[F[Throwable, _]] = {
val svc = HttpRoutes.of(router(ws))
loggingMiddle(svc)
}

protected def router(ws: WebSocketBuilder2[F[Throwable, _]]): PartialFunction[Request[F[Throwable, _]], F[Throwable, Response[F[Throwable, _]]]] = {
protected def router(ws: WebSocketBuilder[F[Throwable, _]]): PartialFunction[Request[F[Throwable, _]], F[Throwable, Response[F[Throwable, _]]]] = {
case request @ GET -> Root / "ws" => setupWs(request, ws)
case request @ GET -> Root / service / method => processHttpRequest(request, service, method)("{}")
case request @ POST -> Root / service / method => request.decode[String](processHttpRequest(request, service, method))
case request @ POST -> Root / service / method => request.decode(processHttpRequest(request, service, method))
}

protected def setupWs(
request: Request[F[Throwable, _]],
ws: WebSocketBuilder2[F[Throwable, _]],
ws: WebSocketBuilder[F[Throwable, _]],
): F[Throwable, Response[F[Throwable, _]]] = {
Quirks.discard(request)
def pingStream(clientSession: WsClientSession[F, AuthCtx]): Stream[F[Throwable, _], WebSocketFrame] = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package izumi.idealingua.runtime.rpc.http4s.clients

import cats.effect.Async
import fs2.Stream
import io.circe
import io.circe.parser.parse
import izumi.functional.bio.{Exit, F, IO2}
Expand All @@ -10,7 +9,8 @@ import izumi.idealingua.runtime.rpc.http4s.IRTUnexpectedHttpStatus
import izumi.idealingua.runtime.rpc.http4s.clients.HttpRpcDispatcher.IRTDispatcherRaw
import logstage.LogIO2
import org.http4s.client.Client
import org.http4s.{Request, Response, Status, Uri}
import org.http4s.{Entity, Request, Response, Status, Uri}
import scodec.bits.ByteVector

class HttpRpcDispatcher[F[+_, +_]: IO2](
client: Client[F[Throwable, _]],
Expand Down Expand Up @@ -92,7 +92,7 @@ class HttpRpcDispatcher[F[+_, +_]: IO2](
): Request[F[Throwable, _]] = {
val uri = baseUri / method.service.value / method.methodId.value
if (body.nonEmpty) {
Request[F[Throwable, _]](org.http4s.Method.POST, uri, body = Stream.emits[F[Throwable, _], Byte](body))
Request[F[Throwable, _]](org.http4s.Method.POST, uri, entity = Entity.strict(ByteVector.view(body)))
} else {
Request[F[Throwable, _]](org.http4s.Method.GET, uri)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ package izumi.idealingua.runtime.rpc.http4s.clients

import cats.effect.Async
import io.circe
import izumi.functional.bio.{F, IO2}
import izumi.functional.bio.{Applicative2, F, IO2}
import izumi.functional.lifecycle.Lifecycle
import izumi.fundamentals.platform.language.Quirks.Discarder
import izumi.idealingua.runtime.rpc.http4s.HttpExecutionContext
import izumi.idealingua.runtime.rpc.{IRTClientMultiplexor, IRTMethodId, IRTMuxRequest, IRTMuxResponse}
import logstage.LogIO2
import izumi.logstage.api.rendering.AnyEncoded
import logstage.{Log, LogIO2}
import org.http4s.client.Client
import org.http4s.ember.client.EmberClientBuilder
import org.http4s.{Header, Headers, Request, Uri}
import org.typelevel.ci.CIString
import org.typelevel.log4cats.{LoggerFactory, SelfAwareStructuredLogger}

class HttpRpcDispatcherFactory[F[+_, +_]: IO2](
codec: IRTClientMultiplexor[F],
Expand Down Expand Up @@ -64,6 +65,8 @@ class HttpRpcDispatcherFactory[F[+_, +_]: IO2](
protected def emberClient: Lifecycle[F[Throwable, _], Client[F[Throwable, _]]] = {
Lifecycle.fromCats {
emberClientBuilder {
implicit def _logger: LogIO2[F] = logger
import HttpRpcDispatcherFactory._hacky_loggerFactory
EmberClientBuilder.default[F[Throwable, _]]
}.build
}
Expand All @@ -74,3 +77,72 @@ class HttpRpcDispatcherFactory[F[+_, +_]: IO2](
}

}

object HttpRpcDispatcherFactory {

implicit def _hacky_loggerFactory[F[+_, +_]: Applicative2](implicit logger: LogIO2[F]): LoggerFactory[F[Throwable, _]] = new LoggerFactory[F[Throwable, _]] {
override def getLoggerFromName(name: String): SelfAwareStructuredLogger[F[Throwable, _]] = new SelfAwareStructuredLogger[F[Throwable, _]] {
override def isTraceEnabled: F[Throwable, Boolean] = F.pure(true)
override def isDebugEnabled: F[Throwable, Boolean] = F.pure(true)
override def isInfoEnabled: F[Throwable, Boolean] = F.pure(true)
override def isWarnEnabled: F[Throwable, Boolean] = F.pure(true)
override def isErrorEnabled: F[Throwable, Boolean] = F.pure(true)

override def trace(ctx: Map[String, String])(msg: => String): F[Throwable, Unit] =
log(Log.Level.Trace, msg, ctx)
override def trace(ctx: Map[String, String], t: Throwable)(msg: => String): F[Throwable, Unit] =
log(Log.Level.Trace, msg, ctx, t)
override def trace(t: Throwable)(msg: => String): F[Throwable, Unit] =
log(Log.Level.Trace, msg, t = t)
override def trace(msg: => String): F[Throwable, Unit] =
log(Log.Level.Trace, msg)

override def debug(ctx: Map[String, String])(msg: => String): F[Throwable, Unit] =
log(Log.Level.Debug, msg, ctx)
override def debug(ctx: Map[String, String], t: Throwable)(msg: => String): F[Throwable, Unit] =
log(Log.Level.Debug, msg, ctx, t)
override def debug(t: Throwable)(msg: => String): F[Throwable, Unit] =
log(Log.Level.Debug, msg, t = t)
override def debug(msg: => String): F[Throwable, Unit] =
log(Log.Level.Debug, msg)

override def info(ctx: Map[String, String])(msg: => String): F[Throwable, Unit] =
log(Log.Level.Info, msg, ctx)
override def info(ctx: Map[String, String], t: Throwable)(msg: => String): F[Throwable, Unit] =
log(Log.Level.Info, msg, ctx, t)
override def info(t: Throwable)(msg: => String): F[Throwable, Unit] =
log(Log.Level.Info, msg, t = t)
override def info(msg: => String): F[Throwable, Unit] =
log(Log.Level.Info, msg)

override def warn(ctx: Map[String, String])(msg: => String): F[Throwable, Unit] =
log(Log.Level.Warn, msg, ctx)
override def warn(ctx: Map[String, String], t: Throwable)(msg: => String): F[Throwable, Unit] =
log(Log.Level.Warn, msg, ctx, t)
override def warn(t: Throwable)(msg: => String): F[Throwable, Unit] =
log(Log.Level.Warn, msg, t = t)
override def warn(msg: => String): F[Throwable, Unit] =
log(Log.Level.Warn, msg)

override def error(ctx: Map[String, String])(msg: => String): F[Throwable, Unit] =
log(Log.Level.Error, msg, ctx)
override def error(ctx: Map[String, String], t: Throwable)(msg: => String): F[Throwable, Unit] =
log(Log.Level.Error, msg, ctx, t)
override def error(t: Throwable)(msg: => String): F[Throwable, Unit] =
log(Log.Level.Error, msg, t = t)
override def error(msg: => String): F[Throwable, Unit] =
log(Log.Level.Error, msg)

private[this] def log(level: Log.Level, msg: => String, ctx: Map[String, String] = null, t: Throwable = null): F[Nothing, Unit] = {
import scala.util.chaining.*
logger
.pipe(l => Option(ctx).fold(l)(c => l.withCustomContextMap(c.view.mapValues(AnyEncoded.to).toMap)))
.pipe(l => Option(t).fold(l)(t => l.withCustomContext("error" -> t)))
.log(level)(Log.Message.raw(msg))
}
}

override def fromName(name: String): F[Throwable, SelfAwareStructuredLogger[F[Throwable, _]]] = F.pure(getLoggerFromName(name))
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ object Http4sTransportTest {
port = addr.getPort
host = addr.getHostName
_ <- Lifecycle.fromCats {
implicit def _logger: LogIO2[F] = logger
import HttpRpcDispatcherFactory._hacky_loggerFactory
EmberServerBuilder
.default[F[Throwable, _]]
.withPort(Port.fromInt(port).get)
Expand Down
7 changes: 2 additions & 5 deletions project/Deps.sc
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,6 @@ object Idealingua {
import Deps._

// DON'T REMOVE, these variables are read from CI build (build.sh)
final val scala212 = ScalaVersion("2.12.19")
final val scala213 = ScalaVersion("2.13.14")
final val scala300 = ScalaVersion("3.4.2")

Expand All @@ -145,9 +144,8 @@ object Idealingua {

object Targets {
// switch order to use 2.13 in IDEA
// val targetScala = Seq(scala212, scala213)
val targetScala2 = Seq(scala213, scala212)
val targetScala3 = Seq(scala300, scala213, scala212)
val targetScala2 = Seq(scala213)
val targetScala3 = Seq(scala300, scala213)
private val jvmPlatform2 = PlatformEnv(
platform = Platform.Jvm,
language = targetScala2,
Expand Down Expand Up @@ -265,7 +263,6 @@ object Idealingua {
"testOptions" in SettingScope.Test += """Tests.Argument("-oDF")""".raw,
// "testOptions" in (SettingScope.Test, Platform.Jvm) ++= s"""Seq(Tests.Argument("-u"), Tests.Argument(s"$${target.value}/junit-xml-$${scalaVersion.value}"))""".raw,
"scalacOptions" ++= Seq(
SettingKey(Some(scala212), None) := Defaults.Scala212Options,
SettingKey(Some(scala213), None) := Defaults.Scala213Options,
SettingKey(Some(scala300), None) := Defaults.Scala3Options,
SettingKey.Default := Const.EmptySeq,
Expand Down
4 changes: 2 additions & 2 deletions project/Versions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ object V {

val scalatest = "3.2.18"

val http4s = "0.23.27"
val http4s_ember = "0.23.27"
val http4s = "1.0.0-M41"
val http4s_ember = "1.0.0-M41"

val scalameta = "4.9.5" // Not available for Scala 3 yet
val fastparse = "3.1.0" // 3.0.0 is available for Scala 3
Expand Down
2 changes: 1 addition & 1 deletion version.sbt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ThisBuild / version := "1.3.13-SNAPSHOT"
ThisBuild / version := "1.3.14-SNAPSHOT"