diff --git a/.scala-steward.conf b/.scala-steward.conf index 00036a4335..1c2b076ddc 100644 --- a/.scala-steward.conf +++ b/.scala-steward.conf @@ -6,7 +6,7 @@ updates.ignore = [ updates.pin = [ {groupId = "com.typesafe.akka", version = "2.6."}, {groupId = "org.slf4j", artifactId = "slf4j-api", version = "1."}, - {groupId = "org.scala-lang", artifactId = "scala3-library", version = "3.3."}, - {groupId = "org.scala-lang", artifactId = "scala3-library_sjs1", version = "3.3."}, - {groupId = "org.scala-lang", artifactId = "scala3-library_sjs1_3", version = "3.3."} + {groupId = "org.scala-lang", artifactId = "scala3-library", version = "3.9."}, + {groupId = "org.scala-lang", artifactId = "scala3-library_sjs1", version = "3.9."}, + {groupId = "org.scala-lang", artifactId = "scala3-library_sjs1_3", version = "3.9."} ] diff --git a/.scalafmt.conf b/.scalafmt.conf index 6576656c67..b16eb5b56a 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -1,6 +1,6 @@ version = 3.11.5 maxColumn = 120 -runner.dialect = scala213 +runner.dialect = scala213source3 fileOverride { "glob:**/scala-3/**" { runner.dialect = scala3 diff --git a/README.md b/README.md index dbcf46d259..de9804ca68 100755 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ sttp client is an open-source HTTP client for Scala, supporting various approaches to writing Scala code: synchronous (direct-style), `Future`-based, and using functional effect systems (cats-effect, ZIO, Monix, Kyo, scalaz). -The library is available for Scala 2.12, 2.13 and 3. Supported platforms are the JVM (Java 11+), Scala.JS and Scala Native. +The library is available for Scala 2.12, 2.13 and 3. Supported platforms are the JVM (Java 11+ for Scala 2, Java 17+ for Scala 3), Scala.JS and Scala Native. Here's a quick example of sttp client in action, runnable using [scala-cli](https://scala-cli.virtuslab.org): diff --git a/armeria-backend/src/main/scala/sttp/client4/armeria/AbstractArmeriaBackend.scala b/armeria-backend/src/main/scala/sttp/client4/armeria/AbstractArmeriaBackend.scala index c3f1029ce5..52185a3cb3 100644 --- a/armeria-backend/src/main/scala/sttp/client4/armeria/AbstractArmeriaBackend.scala +++ b/armeria-backend/src/main/scala/sttp/client4/armeria/AbstractArmeriaBackend.scala @@ -50,7 +50,7 @@ abstract class AbstractArmeriaBackend[F[_], S <: Streams[S]]( val streams: Streams[S] - type R = S with Effect[F] + type R = S & Effect[F] protected def bodyFromStreamMessage: BodyFromStreamMessage[F, S] @@ -108,7 +108,7 @@ abstract class AbstractArmeriaBackend[F[_], S <: Streams[S]]( } finally captor.close() } - private def requestToArmeria(request: GenericRequest[_, R]): WebClientRequestPreparation = { + private def requestToArmeria(request: GenericRequest[?, R]): WebClientRequestPreparation = { val requestPreparation = client .prepare() .disablePathParams() @@ -159,7 +159,7 @@ abstract class AbstractArmeriaBackend[F[_], S <: Streams[S]]( case ByteBufferBody(b, _) => requestPreparation.content(contentType, HttpData.wrap(Unpooled.wrappedBuffer(b))) case multipart: MultipartBody[_] => - val armeriaMultipart = Multipart.of(multipart.parts.map(toArmeriaBodyPart): _*) + val armeriaMultipart = Multipart.of(multipart.parts.map(toArmeriaBodyPart)*) requestPreparation.content( contentType.withParameter("boundary", armeriaMultipart.boundary()), armeriaMultipart.toStreamMessage @@ -186,7 +186,7 @@ abstract class AbstractArmeriaBackend[F[_], S <: Streams[S]]( case _ => HttpMethod.UNKNOWN } - private def toArmeriaBodyPart(bodyPart: Part[BodyPart[_]]): ArmeriaBodyPart = { + private def toArmeriaBodyPart(bodyPart: Part[BodyPart[?]]): ArmeriaBodyPart = { val dispositionBuilder = ContentDisposition.builder("form-data") dispositionBuilder.name(bodyPart.name) bodyPart.fileName.foreach(dispositionBuilder.filename) @@ -219,7 +219,7 @@ abstract class AbstractArmeriaBackend[F[_], S <: Streams[S]]( }).build() } - private def adjustExceptions[T](request: GenericRequest[_, _])(execute: => F[T]): F[T] = + private def adjustExceptions[T](request: GenericRequest[?, ?])(execute: => F[T]): F[T] = SttpClientException.adjustExceptions(monad)(execute) { case ex: UnprocessedRequestException => // The cause of an UnprocessedRequestException is always not null diff --git a/armeria-backend/src/main/scala/sttp/client4/armeria/ArmeriaWebClient.scala b/armeria-backend/src/main/scala/sttp/client4/armeria/ArmeriaWebClient.scala index 3adf5c24d9..d23f3bf9e9 100644 --- a/armeria-backend/src/main/scala/sttp/client4/armeria/ArmeriaWebClient.scala +++ b/armeria-backend/src/main/scala/sttp/client4/armeria/ArmeriaWebClient.scala @@ -13,7 +13,7 @@ object ArmeriaWebClient { .build() /** Create a new [[WebClient]] which is adjusted for sttp client's needs. */ - def newClient(): WebClient = newClient(identity[WebClientBuilder] _) + def newClient(): WebClient = newClient(identity[WebClientBuilder](_)) /** Create a new [[WebClient]] which is adjusted for sttp client's needs. */ def newClient(customizeWebClient: WebClientBuilder => WebClientBuilder): WebClient = diff --git a/armeria-backend/src/main/scala/sttp/client4/armeria/BodyFromStreamMessage.scala b/armeria-backend/src/main/scala/sttp/client4/armeria/BodyFromStreamMessage.scala index c1d9a71169..2ecd1f31d9 100644 --- a/armeria-backend/src/main/scala/sttp/client4/armeria/BodyFromStreamMessage.scala +++ b/armeria-backend/src/main/scala/sttp/client4/armeria/BodyFromStreamMessage.scala @@ -70,7 +70,7 @@ private[armeria] trait BodyFromStreamMessage[F[_], S] { } def bytesToPublisher(b: Array[Byte]): F[StreamMessage[HttpData]] = - StreamMessage.of(Array(HttpData.wrap(b)): _*).unit + StreamMessage.of(Array(HttpData.wrap(b))*).unit def pathToPublisher(f: Path): F[StreamMessage[HttpData]] = (StreamMessage.of(f): StreamMessage[HttpData]).unit @@ -109,7 +109,7 @@ private[armeria] trait BodyFromStreamMessage[F[_], S] { (publisherToStream(response), () => monad.eval(response.abort())).unit override protected def handleWS[T]( - responseAs: GenericWebSocketResponseAs[T, _], + responseAs: GenericWebSocketResponseAs[T, ?], meta: ResponseMetadata, ws: Nothing ): F[T] = ws diff --git a/armeria-backend/src/main/scala/sttp/client4/armeria/StreamMessageAggregator.scala b/armeria-backend/src/main/scala/sttp/client4/armeria/StreamMessageAggregator.scala index 169b06b505..f16980549c 100644 --- a/armeria-backend/src/main/scala/sttp/client4/armeria/StreamMessageAggregator.scala +++ b/armeria-backend/src/main/scala/sttp/client4/armeria/StreamMessageAggregator.scala @@ -8,7 +8,7 @@ import scala.collection.mutable private final class StreamMessageAggregator extends Subscriber[HttpData] { private val contentList: mutable.Buffer[HttpData] = new mutable.ArrayBuffer() private var contentLength: Int = 0 - private var subscription: Subscription = _ + private var subscription: Subscription = null val future: CompletableFuture[HttpData] = new CompletableFuture() diff --git a/armeria-backend/zio/src/main/scala/sttp/client4/armeria/zio/package.scala b/armeria-backend/zio/src/main/scala/sttp/client4/armeria/zio/package.scala index fc1e754c64..0252823669 100644 --- a/armeria-backend/zio/src/main/scala/sttp/client4/armeria/zio/package.scala +++ b/armeria-backend/zio/src/main/scala/sttp/client4/armeria/zio/package.scala @@ -35,7 +35,7 @@ package object zio { * [[Request.response]]). Or a failed effect, if an exception occurred when connecting to the target host, writing * the request or reading the response. */ - def send[T, C >: ZioStreams with Effect[Task]]( + def send[T, C >: ZioStreams & Effect[Task]]( request: StreamRequest[T, C] ): ZIO[SttpClient, Throwable, Response[T]] = ZIO.serviceWithZIO[SttpClient](request.send[Task, ZioStreams]) @@ -43,9 +43,9 @@ package object zio { /** A variant of [[send]] which allows the effects that are part of the response handling specification (when using * resource-safe streaming) to use an `R` environment. */ - def sendR[T, C >: ZioStreams with Effect[RIO[R, *]], R]( + def sendR[T, C >: ZioStreams & Effect[RIO[R, *]], R]( request: StreamRequest[T, C] - ): ZIO[SttpClient with R, Throwable, Response[T]] = { + ): ZIO[SttpClient & R, Throwable, Response[T]] = { import sttp.client4.impl.zio.StreamBackendExtendEnv ZIO.serviceWithZIO[SttpClient](b => request.send[RIO[R, *], ZioStreams](b.extendEnv[R])) } diff --git a/armeria-backend/zio/src/test/scala/sttp/client4/armeria/zio/ArmeriaZioStreamingTest.scala b/armeria-backend/zio/src/test/scala/sttp/client4/armeria/zio/ArmeriaZioStreamingTest.scala index 60bbe5a139..c0d4a8f9bf 100644 --- a/armeria-backend/zio/src/test/scala/sttp/client4/armeria/zio/ArmeriaZioStreamingTest.scala +++ b/armeria-backend/zio/src/test/scala/sttp/client4/armeria/zio/ArmeriaZioStreamingTest.scala @@ -27,7 +27,7 @@ class ArmeriaZioStreamingTest extends StreamingTest[Task, ZioStreams] with ZioTe override implicit val convertToFuture: ConvertToFuture[Task] = convertZioTaskToFuture override def bodyProducer(arrays: Iterable[Array[Byte]]): Stream[Throwable, Byte] = - ZStream.fromChunks(arrays.map(Chunk.fromArray).toSeq: _*) + ZStream.fromChunks(arrays.map(Chunk.fromArray).toSeq*) override def bodyConsumer(stream: Stream[Throwable, Byte]): Task[String] = stream.runCollect.map(bytes => new String(bytes.toArray, Utf8)) diff --git a/armeria-backend/zio1/src/main/scala/sttp/client4/armeria/zio/zio.scala b/armeria-backend/zio1/src/main/scala/sttp/client4/armeria/zio/zio.scala index f554ca92be..079aaaa52b 100644 --- a/armeria-backend/zio1/src/main/scala/sttp/client4/armeria/zio/zio.scala +++ b/armeria-backend/zio1/src/main/scala/sttp/client4/armeria/zio/zio.scala @@ -33,7 +33,7 @@ package object zio { * Known exceptions are converted to one of `SttpClientException`. Other exceptions are kept unchanged. */ def send[T]( - request: GenericRequest[T, Effect[Task] with ZioStreams] + request: GenericRequest[T, Effect[Task] & ZioStreams] ): ZIO[SttpClient, Throwable, Response[T]] = ZIO.accessM(env => env.get[SttpClient.Service].send(request)) @@ -41,8 +41,8 @@ package object zio { * websockets or resource-safe streaming) to use an `R` environment. */ def sendR[T, R]( - request: GenericRequest[T, Effect[RIO[R, *]] with ZioStreams] - ): ZIO[SttpClient with R, Throwable, Response[T]] = + request: GenericRequest[T, Effect[RIO[R, *]] & ZioStreams] + ): ZIO[SttpClient & R, Throwable, Response[T]] = ZIO.accessM(env => env.get[SttpClient.Service].extendEnv[R].send(request)) object SttpClientStubbing extends StreamClientStubbing[Any, ZioStreams] { @@ -53,14 +53,14 @@ package object zio { object stubbing { import SttpClientStubbing.StubbingWhenRequest - def whenRequestMatches(p: GenericRequest[_, _] => Boolean): StubbingWhenRequest = + def whenRequestMatches(p: GenericRequest[?, ?] => Boolean): StubbingWhenRequest = StubbingWhenRequest(p) val whenAnyRequest: StubbingWhenRequest = StubbingWhenRequest(_ => true) def whenRequestMatchesPartial( - partial: PartialFunction[GenericRequest[_, _], Response[StubBody]] + partial: PartialFunction[GenericRequest[?, ?], Response[StubBody]] ): URIO[SttpClientStubbing, Unit] = ZIO.accessM(_.get.whenRequestMatchesPartial(partial)) } diff --git a/armeria-backend/zio1/src/test/scala/sttp/client4/armeria/zio/ArmeriaZioStreamingTest.scala b/armeria-backend/zio1/src/test/scala/sttp/client4/armeria/zio/ArmeriaZioStreamingTest.scala index 976c9959b9..e8bf2eaad7 100644 --- a/armeria-backend/zio1/src/test/scala/sttp/client4/armeria/zio/ArmeriaZioStreamingTest.scala +++ b/armeria-backend/zio1/src/test/scala/sttp/client4/armeria/zio/ArmeriaZioStreamingTest.scala @@ -27,7 +27,7 @@ class ArmeriaZioStreamingTest extends StreamingTest[Task, ZioStreams] with ZioTe override implicit val convertToFuture: ConvertToFuture[Task] = convertZioTaskToFuture override def bodyProducer(arrays: Iterable[Array[Byte]]): Stream[Throwable, Byte] = - Stream.fromChunks(arrays.map(Chunk.fromArray).toSeq: _*) + Stream.fromChunks(arrays.map(Chunk.fromArray).toSeq*) override def bodyConsumer(stream: Stream[Throwable, Byte]): Task[String] = stream.runCollect.map(bytes => new String(bytes.toArray, Utf8)) diff --git a/build.sbt b/build.sbt index f58e875d70..97ef1f5452 100644 --- a/build.sbt +++ b/build.sbt @@ -10,7 +10,7 @@ import com.softwaremill.SbtSoftwareMillBrowserTestJS._ val scala2_12 = "2.12.21" val scala2_13 = "2.13.18" -val scala3 = "3.3.8" +val scala3 = "3.9.0" val scala2 = List(scala2_12, scala2_13) val scala2And3 = scala2 ++ List(scala3) @@ -48,14 +48,30 @@ ideSkipProject := (scalaVersion.value != ideScalaVersion) || bspEnabled := !ideSkipProject.value mimaPreviousArtifacts := Set.empty // we only use MiMa for `core` for now, using enableMimaSettings -val commonJvmSettings = Seq( +val commonSettings = Seq( + scalacOptions ++= { + if (ScalaArtifacts.isScala3(scalaVersion.value)) Nil + else if (scalaVersion.value.startsWith("2.12")) Seq("-Xsource:3") + else Seq("-Xsource:3", "-Wconf:cat=scala3-migration:w") + } +) + +// scalac 2.12 overflows the stack when compiling the http4s backend tests with -Xsource:3 +val http4sTestSettings = Seq( + Test / scalacOptions := { + val options = (Test / scalacOptions).value + if (scalaVersion.value.startsWith("2.12")) options.filterNot(_ == "-Xsource:3") else options + } +) + +val commonJvmSettings = commonSettings ++ Seq( scalacOptions ++= - (if (ScalaArtifacts.isScala3(scalaVersion.value)) Seq("-Yfuture-lazy-vals", "-java-output-version", "11") + (if (ScalaArtifacts.isScala3(scalaVersion.value)) Seq("-java-output-version", "17") else Seq("-release", "11")), Test / testOptions += Tests.Argument("-oD") // add test timings; js build specify other options which conflict ) -val commonJsSettings = Seq( +val commonJsSettings = commonSettings ++ Seq( scalaJSLinkerConfig ~= { _.withBatchMode(true).withParallel(false) }, @@ -85,7 +101,7 @@ val commonJsBackendSettings = List( ) ) -val commonNativeSettings: Seq[Def.Setting[?]] = Seq.empty +val commonNativeSettings: Seq[Def.Setting[?]] = commonSettings val versioningSchemeSettings = Seq(versionScheme := Some("early-semver")) @@ -668,6 +684,7 @@ lazy val okhttpMonixBackend = lazy val http4sCe2Backend = (projectMatrix in file("http4s-ce2-backend")) .settings(commonJvmSettings) .settings(testServerSettings) + .settings(http4sTestSettings) .settings( name := "http4s-ce2-backend", libraryDependencies ++= Seq( @@ -680,6 +697,7 @@ lazy val http4sCe2Backend = (projectMatrix in file("http4s-ce2-backend")) lazy val http4sBackend = (projectMatrix in file("http4s-backend")) .settings(testServerSettings) + .settings(http4sTestSettings) .settings( name := "http4s-backend", libraryDependencies ++= Seq( diff --git a/caching/src/main/scala/sttp/client4/caching/CachingBackend.scala b/caching/src/main/scala/sttp/client4/caching/CachingBackend.scala index 6a5560f44d..1c75f671f3 100644 --- a/caching/src/main/scala/sttp/client4/caching/CachingBackend.scala +++ b/caching/src/main/scala/sttp/client4/caching/CachingBackend.scala @@ -37,7 +37,7 @@ class CachingBackend[F[_], P](delegate: GenericBackend[F, P], cache: Cache[F], c import sttp.monad.syntax._ - override def send[T](request: GenericRequest[T, P with Effect[F]]): F[Response[T]] = { + override def send[T](request: GenericRequest[T, P & Effect[F]]): F[Response[T]] = { val cacheableFromConfig = config.eligibleForCaching(request) // Only requests with "cache-friendly" response-as descriptions can be cached, so that we can convert a cached @@ -70,7 +70,7 @@ class CachingBackend[F[_], P](delegate: GenericBackend[F, P], cache: Cache[F], c override def close(): F[Unit] = super.close().ensure(cache.close()) - private def sendNotInCache[T](request: GenericRequest[T, P with Effect[F]], key: Array[Byte]): F[Response[T]] = { + private def sendNotInCache[T](request: GenericRequest[T, P & Effect[F]], key: Array[Byte]): F[Response[T]] = { // Replacing the original response as with a byte array; we know that response-as is cache-friendly, so we'll be // able to obtain a T-body later. val byteArrayRequest = requestWithResponseAsByteArray(request) @@ -93,14 +93,14 @@ class CachingBackend[F[_], P](delegate: GenericBackend[F, P], cache: Cache[F], c private def adjustResponseReadFromCache[T]( responseFromCache: Response[Array[Byte]], - request: GenericRequest[T, _] + request: GenericRequest[T, ?] ): Response[T] = { // We assume that it has been verified that responseAs is cache-friendly, so this won't throw an UOE. val body: T = runResponseAs(request.response.delegate, responseFromCache.body, responseFromCache) responseFromCache.copy(body = body) } - private def responseAsCacheFriendly(responseAs: GenericResponseAs[_, _]): Boolean = + private def responseAsCacheFriendly(responseAs: GenericResponseAs[?, ?]): Boolean = responseAs match { case IgnoreResponse => true case ResponseAsByteArray => true @@ -119,7 +119,7 @@ class CachingBackend[F[_], P](delegate: GenericBackend[F, P], cache: Cache[F], c } private def runResponseAs[T]( - responseAs: GenericResponseAs[T, _], + responseAs: GenericResponseAs[T, ?], data: Array[Byte], responseMetadata: ResponseMetadata ): T = @@ -146,8 +146,8 @@ class CachingBackend[F[_], P](delegate: GenericBackend[F, P], cache: Cache[F], c } private def requestWithResponseAsByteArray[T]( - request: GenericRequest[T, P with Effect[F]] - ): GenericRequest[Array[Byte], P with Effect[F]] = + request: GenericRequest[T, P & Effect[F]] + ): GenericRequest[Array[Byte], P & Effect[F]] = request match { case r: Request[T] @unchecked => r.response(asByteArrayAlways) case _ => throw new IllegalStateException("WebSocket/streaming requests are not cacheable!") diff --git a/caching/src/test/scala/sttp/client4/caching/CachingBackendTest.scala b/caching/src/test/scala/sttp/client4/caching/CachingBackendTest.scala index 87d61bafe6..dc9a36535b 100644 --- a/caching/src/test/scala/sttp/client4/caching/CachingBackendTest.scala +++ b/caching/src/test/scala/sttp/client4/caching/CachingBackendTest.scala @@ -20,7 +20,7 @@ class CachingBackendTest extends AnyFlatSpec with Matchers { def timePassed(seconds: Int): Unit } - def newInMemoryCache = new StubCache[Identity] { + def newInMemoryCache: StubCache[Identity] = new StubCache[Identity] { var storage = new collection.mutable.HashMap[List[Byte], (Array[Byte], Long)]() var now = 0L // how many seconds have passed till the dawn of time diff --git a/core/src/main/scala/sttp/client4/ResponseAs.scala b/core/src/main/scala/sttp/client4/ResponseAs.scala index 231ebc5836..2429eb788e 100644 --- a/core/src/main/scala/sttp/client4/ResponseAs.scala +++ b/core/src/main/scala/sttp/client4/ResponseAs.scala @@ -264,8 +264,8 @@ case class StreamResponseAs[+T, S](delegate: GenericResponseAs[T, S]) extends Re * @see * [[ResponseAs]] */ -case class WebSocketResponseAs[F[_], +T](delegate: GenericResponseAs[T, Effect[F] with WebSockets]) - extends ResponseAsDelegate[T, Effect[F] with WebSockets] { +case class WebSocketResponseAs[F[_], +T](delegate: GenericResponseAs[T, Effect[F] & WebSockets]) + extends ResponseAsDelegate[T, Effect[F] & WebSockets] { /** Applies the given function `f` to the deserialized value `T`. */ def map[T2](f: T => T2): WebSocketResponseAs[F, T2] = @@ -305,8 +305,8 @@ case class WebSocketResponseAs[F[_], +T](delegate: GenericResponseAs[T, Effect[F * @see * [[ResponseAs]] */ -case class WebSocketStreamResponseAs[+T, S](delegate: GenericResponseAs[T, S with WebSockets]) - extends ResponseAsDelegate[T, S with WebSockets] { +case class WebSocketStreamResponseAs[+T, S](delegate: GenericResponseAs[T, S & WebSockets]) + extends ResponseAsDelegate[T, S & WebSockets] { /** Applies the given function `f` to the deserialized value `T`. */ def map[T2](f: T => T2): WebSocketStreamResponseAs[T2, S] = @@ -380,7 +380,7 @@ object GenericResponseAs { } ) - def isWebSocket(ra: GenericResponseAs[_, _]): Boolean = + def isWebSocket(ra: GenericResponseAs[?, ?]): Boolean = ra match { case _: GenericWebSocketResponseAs[_, _] => true case ResponseAsFromMetadata(conditions, default) => @@ -402,13 +402,13 @@ case object ResponseAsByteArray extends GenericResponseAs[Array[Byte], Any] { // fact that `BinaryStream =:= s.BinaryStream`. We have to rely on correct construction via the companion object and // perform typecasts when the request is deconstructed. case class ResponseAsStream[F[_], T, Stream, S] private (s: Streams[S], f: (Stream, ResponseMetadata) => F[T]) - extends GenericResponseAs[T, S with Effect[F]] { + extends GenericResponseAs[T, S & Effect[F]] { override def show: String = "as stream" } object ResponseAsStream { def apply[F[_], T, S](s: Streams[S])( f: (s.BinaryStream, ResponseMetadata) => F[T] - ): GenericResponseAs[T, S with Effect[F]] = + ): GenericResponseAs[T, S & Effect[F]] = new ResponseAsStream(s, f) } @@ -432,15 +432,14 @@ case class ResponseAsFile(output: SttpFile) extends GenericResponseAs[SttpFile, sealed trait GenericWebSocketResponseAs[T, -R] extends GenericResponseAs[T, R] case class ResponseAsWebSocket[F[_], T](f: (WebSocket[F], ResponseMetadata) => F[T]) - extends GenericWebSocketResponseAs[T, WebSockets with Effect[F]] { + extends GenericWebSocketResponseAs[T, WebSockets & Effect[F]] { override def show: String = "as web socket" } -case class ResponseAsWebSocketUnsafe[F[_]]() - extends GenericWebSocketResponseAs[WebSocket[F], WebSockets with Effect[F]] { +case class ResponseAsWebSocketUnsafe[F[_]]() extends GenericWebSocketResponseAs[WebSocket[F], WebSockets & Effect[F]] { override def show: String = "as web socket unsafe" } -case class ResponseAsWebSocketStream[S, Pipe[_, _]](s: Streams[S], p: Pipe[WebSocketFrame.Data[_], WebSocketFrame]) - extends GenericWebSocketResponseAs[Unit, S with WebSockets] { +case class ResponseAsWebSocketStream[S, Pipe[_, _]](s: Streams[S], p: Pipe[WebSocketFrame.Data[?], WebSocketFrame]) + extends GenericWebSocketResponseAs[Unit, S & WebSockets] { override def show: String = "as web socket stream" } diff --git a/core/src/main/scala/sttp/client4/ResponseException.scala b/core/src/main/scala/sttp/client4/ResponseException.scala index 96dc3fd29e..f867b2de17 100644 --- a/core/src/main/scala/sttp/client4/ResponseException.scala +++ b/core/src/main/scala/sttp/client4/ResponseException.scala @@ -47,7 +47,7 @@ object ResponseException { // - @tailrec def find(exception: Throwable): Option[ResponseException[_]] = + @tailrec def find(exception: Throwable): Option[ResponseException[?]] = Option(exception) match { case Some(e: ResponseException[_]) => Some(e) case Some(_) => find(exception.getCause) diff --git a/core/src/main/scala/sttp/client4/RetryWhen.scala b/core/src/main/scala/sttp/client4/RetryWhen.scala index 07dc7eb615..c4bc0b551a 100644 --- a/core/src/main/scala/sttp/client4/RetryWhen.scala +++ b/core/src/main/scala/sttp/client4/RetryWhen.scala @@ -3,7 +3,7 @@ package sttp.client4 import sttp.model.Method object RetryWhen { - def isBodyRetryable(body: GenericRequestBody[_]): Boolean = + def isBodyRetryable(body: GenericRequestBody[?]): Boolean = body match { case NoBody => true case _: StringBody => true diff --git a/core/src/main/scala/sttp/client4/SpecifyAuthScheme.scala b/core/src/main/scala/sttp/client4/SpecifyAuthScheme.scala index 1acb3ab232..2737293624 100644 --- a/core/src/main/scala/sttp/client4/SpecifyAuthScheme.scala +++ b/core/src/main/scala/sttp/client4/SpecifyAuthScheme.scala @@ -5,7 +5,7 @@ import sttp.client4.internal.Utf8 import java.util.Base64 import sttp.attributes.AttributeKey -class SpecifyAuthScheme[+R <: PartialRequestBuilder[R, _]]( +class SpecifyAuthScheme[+R <: PartialRequestBuilder[R, ?]]( hn: String, req: R, digestAttributeKey: AttributeKey[DigestAuthenticator.DigestAuthData] diff --git a/core/src/main/scala/sttp/client4/SttpApi.scala b/core/src/main/scala/sttp/client4/SttpApi.scala index 870c919ff0..ac0132f125 100644 --- a/core/src/main/scala/sttp/client4/SttpApi.scala +++ b/core/src/main/scala/sttp/client4/SttpApi.scala @@ -281,7 +281,7 @@ trait SttpApi extends SttpExtensions with UriInterpolator { */ def asStream[F[_], T, S](s: Streams[S])( f: s.BinaryStream => F[T] - ): StreamResponseAs[Either[String, T], S with Effect[F]] = + ): StreamResponseAs[Either[String, T], S & Effect[F]] = asEither(asStringAlways, asStreamAlways(s)(f)) /** Handles the response body by providing a stream with the response's data to `f`, if the status code is 2xx. @@ -296,7 +296,7 @@ trait SttpApi extends SttpExtensions with UriInterpolator { */ def asStreamOrFail[F[_], T, S](s: Streams[S])( f: s.BinaryStream => F[T] - ): StreamResponseAs[T, S with Effect[F]] = asStream(s)(f).orFail.showAs("as stream or fail") + ): StreamResponseAs[T, S & Effect[F]] = asStream(s)(f).orFail.showAs("as stream or fail") /** Handles the response body by either reading a string (for non-2xx responses), or otherwise providing a stream with * the response's data, along with the response metadata, to `f`. The effect type used by `f` must be compatible with @@ -306,7 +306,7 @@ trait SttpApi extends SttpExtensions with UriInterpolator { */ def asStreamWithMetadata[F[_], T, S](s: Streams[S])( f: (s.BinaryStream, ResponseMetadata) => F[T] - ): StreamResponseAs[Either[String, T], S with Effect[F]] = + ): StreamResponseAs[Either[String, T], S & Effect[F]] = asEither(asStringAlways, asStreamAlwaysWithMetadata(s)(f)) /** Handles the response body by providing a stream with the response's data to `f`, regardless of the status code. @@ -315,7 +315,7 @@ trait SttpApi extends SttpExtensions with UriInterpolator { * * A non-blocking, asynchronous streaming implementation must be provided as the [[Streams]] parameter. */ - def asStreamAlways[F[_], T, S](s: Streams[S])(f: s.BinaryStream => F[T]): StreamResponseAs[T, S with Effect[F]] = + def asStreamAlways[F[_], T, S](s: Streams[S])(f: s.BinaryStream => F[T]): StreamResponseAs[T, S & Effect[F]] = asStreamAlwaysWithMetadata(s)((s, _) => f(s)) /** Handles the response body by providing a stream with the response's data, along with the response metadata, to @@ -326,7 +326,7 @@ trait SttpApi extends SttpExtensions with UriInterpolator { */ def asStreamAlwaysWithMetadata[F[_], T, S](s: Streams[S])( f: (s.BinaryStream, ResponseMetadata) => F[T] - ): StreamResponseAs[T, S with Effect[F]] = StreamResponseAs(ResponseAsStream(s)(f)) + ): StreamResponseAs[T, S & Effect[F]] = StreamResponseAs(ResponseAsStream(s)(f)) /** Handles the response body by either reading a string (for non-2xx responses), or otherwise returning a stream with * the response's data. It's the responsibility of the caller to consume & close the stream. diff --git a/core/src/main/scala/sttp/client4/SttpClientException.scala b/core/src/main/scala/sttp/client4/SttpClientException.scala index cf2df5739f..ffe94116f2 100644 --- a/core/src/main/scala/sttp/client4/SttpClientException.scala +++ b/core/src/main/scala/sttp/client4/SttpClientException.scala @@ -23,25 +23,25 @@ import sttp.monad.MonadError * @param cause * The original exception. */ -sealed abstract class SttpClientException(val request: GenericRequest[_, _], val cause: Exception) +sealed abstract class SttpClientException(val request: GenericRequest[?, ?], val cause: Exception) extends Exception(s"Exception when sending request: ${request.method} ${request.uri}", cause) object SttpClientException extends SttpClientExceptionExtensions { - class ConnectException(request: GenericRequest[_, _], cause: Exception) extends SttpClientException(request, cause) + class ConnectException(request: GenericRequest[?, ?], cause: Exception) extends SttpClientException(request, cause) - class ReadException(request: GenericRequest[_, _], cause: Exception) extends SttpClientException(request, cause) + class ReadException(request: GenericRequest[?, ?], cause: Exception) extends SttpClientException(request, cause) // - class TimeoutException(request: GenericRequest[_, _], cause: Exception) extends ReadException(request, cause) + class TimeoutException(request: GenericRequest[?, ?], cause: Exception) extends ReadException(request, cause) - class TooManyRedirectsException(request: GenericRequest[_, _], val redirects: Int) + class TooManyRedirectsException(request: GenericRequest[?, ?], val redirects: Int) extends ReadException(request, null) /** Wraps a [[ResponseException]] which occurred during response handling. Enriches the response exception with the * context of the request, for which it happened. */ - class ResponseHandlingException[+HE](request: GenericRequest[_, _], val responseException: ResponseException[HE]) + class ResponseHandlingException[+HE](request: GenericRequest[?, ?], val responseException: ResponseException[HE]) extends ReadException(request, responseException) // diff --git a/core/src/main/scala/sttp/client4/SttpWebSocketStreamApi.scala b/core/src/main/scala/sttp/client4/SttpWebSocketStreamApi.scala index 3fc68e9fd5..4c805e3d41 100644 --- a/core/src/main/scala/sttp/client4/SttpWebSocketStreamApi.scala +++ b/core/src/main/scala/sttp/client4/SttpWebSocketStreamApi.scala @@ -15,7 +15,7 @@ trait SttpWebSocketStreamApi { */ def asWebSocketStream[S]( s: Streams[S] - )(p: s.Pipe[WebSocketFrame.Data[_], WebSocketFrame]): WebSocketStreamResponseAs[Either[String, Unit], S] = + )(p: s.Pipe[WebSocketFrame.Data[?], WebSocketFrame]): WebSocketStreamResponseAs[Either[String, Unit], S] = asWebSocketEither(asStringAlways, asWebSocketStreamAlways(s)(p)) /** Handles the response as a web socket, using the given `p` stream processing pipe to handle the incoming & produce @@ -33,7 +33,7 @@ trait SttpWebSocketStreamApi { */ def asWebSocketStreamOrFail[S]( s: Streams[S] - )(p: s.Pipe[WebSocketFrame.Data[_], WebSocketFrame]): WebSocketStreamResponseAs[Unit, S] = + )(p: s.Pipe[WebSocketFrame.Data[?], WebSocketFrame]): WebSocketStreamResponseAs[Unit, S] = asWebSocketStream(s)(p).orFail.showAs("as web socket stream or fail") /** Handles the response body by using the given `p` stream processing pipe to handle the incoming & produce the @@ -44,7 +44,7 @@ trait SttpWebSocketStreamApi { * A non-blocking, asynchronous streaming implementation must be provided as the [[Streams]] parameter. */ def asWebSocketStreamAlways[S](s: Streams[S])( - p: s.Pipe[WebSocketFrame.Data[_], WebSocketFrame] + p: s.Pipe[WebSocketFrame.Data[?], WebSocketFrame] ): WebSocketStreamResponseAs[Unit, S] = WebSocketStreamResponseAs[Unit, S](ResponseAsWebSocketStream(s, p)) /** Uses the [[ResponseAs]] description that matches the condition (using the response's metadata). diff --git a/core/src/main/scala/sttp/client4/backend.scala b/core/src/main/scala/sttp/client4/backend.scala index 9a2147e5f3..a9ca65a9e5 100644 --- a/core/src/main/scala/sttp/client4/backend.scala +++ b/core/src/main/scala/sttp/client4/backend.scala @@ -31,7 +31,7 @@ trait GenericBackend[F[_], +P] { /** Send the given request. Should only be used when implementing new backends, or backend wrappers. Client code * should instead use the `send` methods on the request type, e.g. [[Request.send]]. */ - def send[T](request: GenericRequest[T, P with Effect[F]]): F[Response[T]] + def send[T](request: GenericRequest[T, P & Effect[F]]): F[Response[T]] /** Close the backend, releasing any resources (such as thread or connection pools) that have been allocated when * opening or using the backend. @@ -65,4 +65,4 @@ trait WebSocketBackend[F[_]] extends Backend[F] with GenericBackend[F, WebSocket trait WebSocketStreamBackend[F[_], S] extends WebSocketBackend[F] with StreamBackend[F, S] - with GenericBackend[F, S with WebSockets] + with GenericBackend[F, S & WebSockets] diff --git a/core/src/main/scala/sttp/client4/internal/BodyFromResponseAs.scala b/core/src/main/scala/sttp/client4/internal/BodyFromResponseAs.scala index 6e5452608e..719ea720a9 100644 --- a/core/src/main/scala/sttp/client4/internal/BodyFromResponseAs.scala +++ b/core/src/main/scala/sttp/client4/internal/BodyFromResponseAs.scala @@ -10,13 +10,13 @@ import java.io.InputStream abstract class BodyFromResponseAs[F[_], RegularResponse, WSResponse, Stream](implicit m: MonadError[F]) { def apply[T]( - responseAs: ResponseAsDelegate[T, _], + responseAs: ResponseAsDelegate[T, ?], meta: ResponseMetadata, response: Either[RegularResponse, WSResponse] ): F[T] = doApply(responseAs.delegate, meta, response).map(_._1) private def doApply[T]( - responseAs: GenericResponseAs[T, _], + responseAs: GenericResponseAs[T, ?], meta: ResponseMetadata, response: Either[RegularResponse, WSResponse] ): F[(T, ReplayableBody)] = @@ -71,7 +71,7 @@ abstract class BodyFromResponseAs[F[_], RegularResponse, WSResponse, Stream](imp regularAsFile(regular, file).map(f => (f, replayableBody(f))) case (wsr: GenericWebSocketResponseAs[_, _], Right(ws)) => - handleWS(wsr.asInstanceOf[GenericWebSocketResponseAs[T, _]], meta, ws) + handleWS(wsr.asInstanceOf[GenericWebSocketResponseAs[T, ?]], meta, ws) .map(w => (w, nonReplayableBody)) case (_: GenericWebSocketResponseAs[_, _], Left(regular)) => @@ -93,7 +93,7 @@ abstract class BodyFromResponseAs[F[_], RegularResponse, WSResponse, Stream](imp protected def regularAsStream(response: RegularResponse): F[(Stream, () => F[Unit])] protected def regularAsInputStream(response: RegularResponse): F[InputStream] = throw new UnsupportedOperationException("Responses as a java.io.InputStream are not supported") - protected def handleWS[T](responseAs: GenericWebSocketResponseAs[T, _], meta: ResponseMetadata, ws: WSResponse): F[T] + protected def handleWS[T](responseAs: GenericWebSocketResponseAs[T, ?], meta: ResponseMetadata, ws: WSResponse): F[T] protected def cleanupWhenNotAWebSocket(response: RegularResponse, e: NotAWebSocketException): F[Unit] protected def cleanupWhenGotWebSocket(response: WSResponse, e: GotAWebSocketException): F[Unit] } diff --git a/core/src/main/scala/sttp/client4/internal/DigestAuthenticator.scala b/core/src/main/scala/sttp/client4/internal/DigestAuthenticator.scala index fbdec4816a..adbcb5560b 100644 --- a/core/src/main/scala/sttp/client4/internal/DigestAuthenticator.scala +++ b/core/src/main/scala/sttp/client4/internal/DigestAuthenticator.scala @@ -15,13 +15,13 @@ private[client4] class DigestAuthenticator private ( unauthorizedStatusCode: StatusCode, clientNonceGenerator: () => String ) { - def authenticate[T](request: GenericRequest[T, _], response: Response[T]): Option[Header] = + def authenticate[T](request: GenericRequest[T, ?], response: Response[T]): Option[Header] = responseHeaderValue(response.headers(requestHeaderName), request, response.code) .map(Header(responseHeaderName, _)) private def responseHeaderValue( authHeaderValues: Seq[String], - request: GenericRequest[_, _], + request: GenericRequest[?, ?], statusCode: StatusCode ): Option[String] = { val wwwAuthRawHeaders = authHeaderValues @@ -42,7 +42,7 @@ private[client4] class DigestAuthenticator private ( } private def responseHeaderValue( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], digestAuthData: DigestAuthData, wwwAuthHeader: WwwAuthHeaderValue, realmMatch: String, @@ -116,7 +116,7 @@ private[client4] class DigestAuthenticator private ( } private def calculateResponseChallenge( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], digestAuthData: DigestAuthData, realm: String, qop: Option[String], @@ -164,7 +164,7 @@ private[client4] class DigestAuthenticator private ( } private def calculateHa2( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], qop: Option[String], digestUri: String, messageDigest: MessageDigestCompatibility diff --git a/core/src/main/scala/sttp/client4/internal/ToCurlConverter.scala b/core/src/main/scala/sttp/client4/internal/ToCurlConverter.scala index 247a8689ca..358c91d326 100644 --- a/core/src/main/scala/sttp/client4/internal/ToCurlConverter.scala +++ b/core/src/main/scala/sttp/client4/internal/ToCurlConverter.scala @@ -6,7 +6,7 @@ import sttp.model._ private[client4] object ToCurlConverter { def apply( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], omitAcceptEncoding: Boolean = false, sensitiveHeaders: Set[String] = HeaderNames.SensitiveHeaders, sensitiveQueryParams: Set[String] = Set.empty @@ -19,20 +19,20 @@ private[client4] object ToCurlConverter { extractOptions(_) ) .map(addSpaceIfNotEmpty) - .reduce((acc, item) => (r: GenericRequest[_, _]) => acc(r) + item(r)) + .reduce((acc, item) => (r: GenericRequest[?, ?]) => acc(r) + item(r)) .apply(request) s"""curl$params""" } - private def extractMethod(r: GenericRequest[_, _]): String = + private def extractMethod(r: GenericRequest[?, ?]): String = s"--request ${r.method.method}" - private def extractUrl(sensitiveQueryParams: Set[String])(r: GenericRequest[_, _]): String = + private def extractUrl(sensitiveQueryParams: Set[String])(r: GenericRequest[?, ?]): String = s"--url '${r.uri.toStringSafe(sensitiveQueryParams)}'" private def extractHeaders(sensitiveHeaders: Set[String], omitAcceptEncoding: Boolean)( - r: GenericRequest[_, _] + r: GenericRequest[?, ?] ): String = (if (!omitAcceptEncoding) { r.headers @@ -43,7 +43,7 @@ private[client4] object ToCurlConverter { .map(h => s"--header '${h.toStringSafe(sensitiveHeaders)}'") .mkString(newline) - private def extractBody(r: GenericRequest[_, _]): String = + private def extractBody(r: GenericRequest[?, ?]): String = r.body match { case StringBody(text, _, _) => s"""--data-raw '${text.replace("'", "\\'")}'""" case ByteArrayBody(_, _) => s"--data-binary " @@ -55,7 +55,7 @@ private[client4] object ToCurlConverter { case NoBody => "" } - def handleMultipartBody(parts: Seq[Part[GenericRequestBody[_]]]): String = + def handleMultipartBody(parts: Seq[Part[GenericRequestBody[?]]]): String = parts .map { p => val formValue = p.body match { @@ -67,7 +67,7 @@ private[client4] object ToCurlConverter { } .mkString(newline) - private def partMetadata(p: Part[GenericRequestBody[_]]): String = { + private def partMetadata(p: Part[GenericRequestBody[?]]): String = { val fileName = p.fileName.fold("")(n => s";filename=${escapeSingleQuotes(n)}") val contentType = p.contentType.fold("")(ct => s";type=${escapeSingleQuotes(ct)}") // Content-Type is already emitted via ;type= so it is filtered out here to avoid duplication. @@ -80,14 +80,14 @@ private[client4] object ToCurlConverter { private def escapeSingleQuotes(text: String): String = text.replace("'", "\\'") - private def extractOptions(r: GenericRequest[_, _]): String = + private def extractOptions(r: GenericRequest[?, ?]): String = if (r.options.followRedirects) { s"--location${newline}--max-redirs ${r.options.maxRedirects}" } else { "" } - private def addSpaceIfNotEmpty(fInput: GenericRequest[_, _] => String): GenericRequest[_, _] => String = + private def addSpaceIfNotEmpty(fInput: GenericRequest[?, ?] => String): GenericRequest[?, ?] => String = t => if (fInput(t).isEmpty) "" else s"${newline}${fInput(t)}" private def newline: String = " \\\n " diff --git a/core/src/main/scala/sttp/client4/internal/ToRfc2616Converter.scala b/core/src/main/scala/sttp/client4/internal/ToRfc2616Converter.scala index 67a0c53a96..d9a3070cbc 100644 --- a/core/src/main/scala/sttp/client4/internal/ToRfc2616Converter.scala +++ b/core/src/main/scala/sttp/client4/internal/ToRfc2616Converter.scala @@ -11,7 +11,7 @@ private[client4] object ToRfc2616Converter { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".toCharArray def apply( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], sensitiveHeaders: Set[String] = HeaderNames.SensitiveHeaders, sensitiveQueryParams: Set[String] = Set.empty ): String = { @@ -24,7 +24,7 @@ private[client4] object ToRfc2616Converter { if (body.isEmpty) resultWithHeaders else resultWithHeaders + s"\n\n$body" } - private def extractBody(r: GenericRequest[_, _]): String = + private def extractBody(r: GenericRequest[?, ?]): String = r.body match { case StringBody(text, _, _) => s"$text" case ByteArrayBody(_, _) => "" @@ -36,7 +36,7 @@ private[client4] object ToRfc2616Converter { case NoBody => "" } - def handleMultipartBody(parts: Seq[Part[GenericRequestBody[_]]]): String = { + def handleMultipartBody(parts: Seq[Part[GenericRequestBody[?]]]): String = { val boundary = generateBoundary() parts .map { p => @@ -57,7 +57,7 @@ private[client4] object ToRfc2616Converter { .mkString("") + s"--$boundary--" } - private def extractHeaders(r: GenericRequest[_, _], sensitiveHeaders: Set[String]): String = + private def extractHeaders(r: GenericRequest[?, ?], sensitiveHeaders: Set[String]): String = r.headers // filtering out compression headers so that the results are human-readable, if possible .filterNot(_.name.equalsIgnoreCase(HeaderNames.AcceptEncoding)) diff --git a/core/src/main/scala/sttp/client4/internal/WwwAuthHeaderParser.scala b/core/src/main/scala/sttp/client4/internal/WwwAuthHeaderParser.scala index ed59b91b14..d375911f4e 100644 --- a/core/src/main/scala/sttp/client4/internal/WwwAuthHeaderParser.scala +++ b/core/src/main/scala/sttp/client4/internal/WwwAuthHeaderParser.scala @@ -18,7 +18,7 @@ private[client4] case class WwwAuthHeaderValue(values: Map[String, String]) { val opaque = values.get("opaque") } -private case class KeyParser private (currentKey: String, parsed: Map[String, String]) extends Parser { +private case class KeyParser(currentKey: String, parsed: Map[String, String]) extends Parser { override def parseNext(input: Char): Parser = if (input == '=') { ValueParser(currentKey, parsed) @@ -35,7 +35,7 @@ private object KeyParser { def apply(parsed: Map[String, String]) = new KeyParser("", parsed) } -private case class ValueParser private ( +private case class ValueParser( currentKey: String, currentValue: String, parsed: Map[String, String] @@ -54,7 +54,7 @@ private object ValueParser { def apply(key: String, parsed: Map[String, String]) = new ValueParser(key, "", parsed) } -private case class QuotedValueParser private ( +private case class QuotedValueParser( currentKey: String, currentValue: String, parsed: Map[String, String] diff --git a/core/src/main/scala/sttp/client4/listener/ListenerBackend.scala b/core/src/main/scala/sttp/client4/listener/ListenerBackend.scala index 43e68c776b..baf8c45ee0 100644 --- a/core/src/main/scala/sttp/client4/listener/ListenerBackend.scala +++ b/core/src/main/scala/sttp/client4/listener/ListenerBackend.scala @@ -13,7 +13,7 @@ abstract class ListenerBackend[F[_], P, L]( delegate: GenericBackend[F, P], listener: RequestListener[F, L] ) extends DelegateBackend(delegate) { - override def send[T](request: GenericRequest[T, P with Effect[F]]): F[Response[T]] = + override def send[T](request: GenericRequest[T, P & Effect[F]]): F[Response[T]] = listener.before(request).flatMap { case tag => val onBodyReceivedCalled = new AtomicBoolean // #2669. It would be best to either: diff --git a/core/src/main/scala/sttp/client4/listener/RequestListener.scala b/core/src/main/scala/sttp/client4/listener/RequestListener.scala index b1841c81f1..0e9285773b 100644 --- a/core/src/main/scala/sttp/client4/listener/RequestListener.scala +++ b/core/src/main/scala/sttp/client4/listener/RequestListener.scala @@ -15,7 +15,7 @@ import sttp.client4.ResponseException trait RequestListener[F[_], L] { /** Called before a request is sent. */ - def before(request: GenericRequest[_, _]): F[L] + def before(request: GenericRequest[?, ?]): F[L] /** Called when the response body has been fully received (see [[sttp.client4.Request#onBodyReceived]]), but not yet * fully handled (e.g. parsed). @@ -25,7 +25,7 @@ trait RequestListener[F[_], L] { * * Note that this method must run any effects immediately, as it returns a `Unit`, without the `F` wrapper. */ - def responseBodyReceived(request: GenericRequest[_, _], response: ResponseMetadata, tag: L): Unit + def responseBodyReceived(request: GenericRequest[?, ?], response: ResponseMetadata, tag: L): Unit /** Called when the request has been handled, as specified by the response description. * @@ -37,10 +37,10 @@ trait RequestListener[F[_], L] { * received via the network, but e.g. a parsing or decompression exception occurs. */ def responseHandled( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], response: ResponseMetadata, tag: L, - exception: Option[ResponseException[_]] + exception: Option[ResponseException[?]] ): F[Unit] /** Called when there's an exception, when receiving the response body or handling the response (decompression, @@ -56,7 +56,7 @@ trait RequestListener[F[_], L] { * Indicates if [[responseBodyReceivedCalled]] has been called before this method. */ def exception( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], tag: L, exception: Throwable, responseBodyReceivedCalled: Boolean @@ -66,22 +66,22 @@ trait RequestListener[F[_], L] { object RequestListener { def lift[F[_], L](delegate: RequestListener[Identity, L], monadError: MonadError[F]): RequestListener[F, L] = new RequestListener[F, L] { - override def before(request: GenericRequest[_, _]): F[L] = + override def before(request: GenericRequest[?, ?]): F[L] = monadError.eval(delegate.before(request)) - override def responseBodyReceived(request: GenericRequest[_, _], response: ResponseMetadata, tag: L): Unit = + override def responseBodyReceived(request: GenericRequest[?, ?], response: ResponseMetadata, tag: L): Unit = delegate.responseBodyReceived(request, response, tag) override def responseHandled( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], response: ResponseMetadata, tag: L, - e: Option[ResponseException[_]] + e: Option[ResponseException[?]] ): F[Unit] = monadError.eval(delegate.responseHandled(request, response, tag, e)) override def exception( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], tag: L, e: Throwable, responseBodyReceivedCalled: Boolean diff --git a/core/src/main/scala/sttp/client4/logging/Log.scala b/core/src/main/scala/sttp/client4/logging/Log.scala index a32f4669f3..50572fe4a1 100644 --- a/core/src/main/scala/sttp/client4/logging/Log.scala +++ b/core/src/main/scala/sttp/client4/logging/Log.scala @@ -9,20 +9,20 @@ import sttp.client4.ResponseException /** Performs logging before requests are sent and after requests complete successfully or with an exception. */ trait Log[F[_]] { - def beforeRequestSend(request: GenericRequest[_, _]): F[Unit] + def beforeRequestSend(request: GenericRequest[?, ?]): F[Unit] /** @param exception * A [[ResponseException]] that might occur when handling the response (e.g. parsing). */ def response( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], response: ResponseMetadata, responseBody: Option[String], timings: Option[ResponseTimings], - exception: Option[ResponseException[_]] + exception: Option[ResponseException[?]] ): F[Unit] - def requestException(request: GenericRequest[_, _], timing: Option[Duration], exception: Throwable): F[Unit] + def requestException(request: GenericRequest[?, ?], timing: Option[Duration], exception: Throwable): F[Unit] } object Log { @@ -44,7 +44,7 @@ object Log { */ class DefaultLog[F[_]](logger: Logger[F], config: LogConfig, logContext: LogContext) extends Log[F] { - def beforeRequestSend(request: GenericRequest[_, _]): F[Unit] = { + def beforeRequestSend(request: GenericRequest[?, ?]): F[Unit] = { val _logRequestBody = request.loggingOptions.logRequestBody.getOrElse(config.logRequestBody) val _logRequestHeaders = request.loggingOptions.logRequestHeaders.getOrElse(config.logRequestHeaders) val _message = @@ -61,11 +61,11 @@ class DefaultLog[F[_]](logger: Logger[F], config: LogConfig, logContext: LogCont } override def response( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], response: ResponseMetadata, responseBody: Option[String], timings: Option[ResponseTimings], - exception: Option[ResponseException[_]] + exception: Option[ResponseException[?]] ): F[Unit] = { val responseWithBody = Response( responseBody.getOrElse(""), @@ -92,7 +92,7 @@ class DefaultLog[F[_]](logger: Logger[F], config: LogConfig, logContext: LogCont } override def requestException( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], timing: Option[Duration], exception: Throwable ): F[Unit] = diff --git a/core/src/main/scala/sttp/client4/logging/LoggingBackend.scala b/core/src/main/scala/sttp/client4/logging/LoggingBackend.scala index c49f6ac1a9..3f21f3f698 100644 --- a/core/src/main/scala/sttp/client4/logging/LoggingBackend.scala +++ b/core/src/main/scala/sttp/client4/logging/LoggingBackend.scala @@ -19,7 +19,7 @@ class LoggingBackend[F[_], P]( includeTimings: Boolean ) extends DelegateBackend[F, P](delegate) { - override def send[T](request: GenericRequest[T, P with Effect[F]]): F[Response[T]] = { + override def send[T](request: GenericRequest[T, P & Effect[F]]): F[Response[T]] = { if (request.loggingOptions.log) { log.beforeRequestSend(request).flatMap { _ => val _includeTimings = request.loggingOptions.includeTimings.getOrElse(includeTimings) @@ -47,7 +47,7 @@ class LoggingBackend[F[_], P]( } private def sendDoNotLogResponseBody[T]( - request: GenericRequest[T, P with Effect[F]], + request: GenericRequest[T, P & Effect[F]], tag: Option[LoggingTag] ): F[Response[T]] = { for { @@ -57,10 +57,10 @@ class LoggingBackend[F[_], P]( } private def sendLogResponseBody[T]( - request: GenericRequest[T, P with Effect[F]], + request: GenericRequest[T, P & Effect[F]], tag: Option[LoggingTag] ): F[Response[T]] = { - def sendAndLog(request: GenericRequest[(T, Option[String]), P with Effect[F]]): F[Response[T]] = + def sendAndLog(request: GenericRequest[(T, Option[String]), P & Effect[F]]): F[Response[T]] = for { r <- delegate.send(request) _ <- log.response(request, r, r.body._2, tag.map(toResponseTimings), None) @@ -69,7 +69,7 @@ class LoggingBackend[F[_], P]( request match { case request: Request[T] @unchecked => sendAndLog(request.response(asBothOption(request.response, asStringAlways))) - case request: StreamRequest[T, P with Effect[F]] @unchecked => + case request: StreamRequest[T, P & Effect[F]] @unchecked => sendAndLog(request.response(asBothOption(request.response, asStringAlways))) case request => for { diff --git a/core/src/main/scala/sttp/client4/monad/MapEffect.scala b/core/src/main/scala/sttp/client4/monad/MapEffect.scala index 93ba7d15df..cd199bd161 100644 --- a/core/src/main/scala/sttp/client4/monad/MapEffect.scala +++ b/core/src/main/scala/sttp/client4/monad/MapEffect.scala @@ -20,18 +20,18 @@ object MapEffect { * The requirements of this request, without the `Effect[F]` capability. */ def apply[F[_], G[_], T, R0]( - r: GenericRequest[T, R0 with Effect[F]], + r: GenericRequest[T, R0 & Effect[F]], fk: FunctionK[F, G], gk: FunctionK[G, F], fm: MonadError[F], gm: MonadError[G] - ): GenericRequest[T, R0 with Effect[G]] = { + ): GenericRequest[T, R0 & Effect[G]] = { def internalResponse[R] = apply[F, G](r.response.delegate, fk, gk, fm, gm) - .asInstanceOf[GenericResponseAs[T, R with Effect[G]]] + .asInstanceOf[GenericResponseAs[T, R & Effect[G]]] // Only StreamRequest and WebSocketRequest can have an effectful response val newRequest = r match { - case srf: StreamRequest[_, R0 with Effect[F]] => + case srf: StreamRequest[_, R0 & Effect[F]] => srf.copy( body = srf.body.asInstanceOf[GenericRequestBody[R0]], response = new StreamResponseAs(internalResponse[R0]) @@ -40,18 +40,18 @@ object MapEffect { wr.copy[G, T](response = new WebSocketResponseAs[G, T](internalResponse[WebSockets])) case _ => r } - newRequest.asInstanceOf[GenericRequest[T, R0 with Effect[G]]] + newRequest.asInstanceOf[GenericRequest[T, R0 & Effect[G]]] } // TODO: an even more dumbed-down version of the slightly more type-safe version below, which is needed due to a // TODO: bug in Dotty: https://github.com/lampepfl/dotty/issues/9533 private def apply[F[_], G[_]]( - r: GenericResponseAs[_, _], + r: GenericResponseAs[?, ?], fk: FunctionK[F, G], gk: FunctionK[G, F], fm: MonadError[F], gm: MonadError[G] - ): GenericResponseAs[_, _] = + ): GenericResponseAs[?, ?] = r match { case IgnoreResponse => IgnoreResponse case ResponseAsByteArray => ResponseAsByteArray @@ -81,7 +81,7 @@ object MapEffect { case MappedResponseAs(raw, g, showAs) => MappedResponseAs(apply[F, G](raw, fk, gk, fm, gm), g.asInstanceOf[(Any, ResponseMetadata) => Any], showAs) case ResponseAsBoth(l, r) => - ResponseAsBoth(apply(l, fk, gk, fm, gm), apply(r, fk, gk, fm, gm).asInstanceOf[GenericResponseAs[_, Any]]) + ResponseAsBoth(apply(l, fk, gk, fm, gm), apply(r, fk, gk, fm, gm).asInstanceOf[GenericResponseAs[?, Any]]) } /* private def apply[TT, R0, F[_], G[_]]( diff --git a/core/src/main/scala/sttp/client4/package.scala b/core/src/main/scala/sttp/client4/package.scala index ec63187771..d35da648df 100644 --- a/core/src/main/scala/sttp/client4/package.scala +++ b/core/src/main/scala/sttp/client4/package.scala @@ -6,5 +6,5 @@ package object client4 extends SttpApi { * @see * [[RetryWhen.Default]] */ - type RetryWhen = (GenericRequest[_, _], Either[Throwable, Response[_]]) => Boolean + type RetryWhen = (GenericRequest[?, ?], Either[Throwable, Response[?]]) => Boolean } diff --git a/core/src/main/scala/sttp/client4/request.scala b/core/src/main/scala/sttp/client4/request.scala index f283380dd2..8549d86fd8 100644 --- a/core/src/main/scala/sttp/client4/request.scala +++ b/core/src/main/scala/sttp/client4/request.scala @@ -251,13 +251,13 @@ final case class StreamRequest[T, R]( def response[T2, R2 <: R](ra: StreamResponseAs[T2, R2]): StreamRequest[T2, R2] = copy(response = ra) /** Specifies that this is a WebSocket request. A [[WebSocketStreamBackend]] will be required to send this request. */ - def response[T2, F[_]](ra: WebSocketResponseAs[F, T2]): WebSocketStreamRequest[T2, Effect[F] with R] = + def response[T2, F[_]](ra: WebSocketResponseAs[F, T2]): WebSocketStreamRequest[T2, Effect[F] & R] = WebSocketStreamRequest( method, uri, body, headers, - WebSocketStreamResponseAs[T2, Effect[F] with R](ra.delegate), + WebSocketStreamResponseAs[T2, Effect[F] & R](ra.delegate), options, attributes ) @@ -283,8 +283,8 @@ final case class StreamRequest[T, R]( * Known exceptions are converted by backends to one of [[SttpClientException]]. Other exceptions are thrown * unchanged. */ - def send[F[_], P](backend: StreamBackend[F, P])(implicit ev: P with Effect[F] <:< R): F[Response[T]] = - backend.send(this.asInstanceOf[StreamRequest[T, P with Effect[F]]]) // as witnessed by ev + def send[F[_], P](backend: StreamBackend[F, P])(implicit ev: (P & Effect[F]) <:< R): F[Response[T]] = + backend.send(this.asInstanceOf[StreamRequest[T, P & Effect[F]]]) // as witnessed by ev } // @@ -313,7 +313,7 @@ final case class WebSocketRequest[F[_], T]( response: WebSocketResponseAs[F, T], options: RequestOptions, attributes: AttributeMap -) extends GenericRequest[T, WebSockets with Effect[F]] +) extends GenericRequest[T, WebSockets & Effect[F]] with RequestBuilder[WebSocketRequest[F, T]] { override def method(method: Method, uri: Uri): WebSocketRequest[F, T] = copy(method = method, uri = uri) @@ -322,13 +322,13 @@ final case class WebSocketRequest[F[_], T]( override def withAttributes(attributes: AttributeMap): WebSocketRequest[F, T] = copy(attributes = attributes) override protected def copyWithBody(body: BasicBody): WebSocketRequest[F, T] = copy(body = body) - def streamBody[S](s: Streams[S])(b: s.BinaryStream): WebSocketStreamRequest[T, Effect[F] with S] = + def streamBody[S](s: Streams[S])(b: s.BinaryStream): WebSocketStreamRequest[T, Effect[F] & S] = WebSocketStreamRequest( method, uri, StreamBody(s)(b), headers, - WebSocketStreamResponseAs[T, Effect[F] with S](response.delegate), + WebSocketStreamResponseAs[T, Effect[F] & S](response.delegate), options, attributes ) @@ -394,7 +394,7 @@ final case class WebSocketStreamRequest[T, S]( response: WebSocketStreamResponseAs[T, S], options: RequestOptions, attributes: AttributeMap -) extends GenericRequest[T, S with WebSockets] +) extends GenericRequest[T, S & WebSockets] with RequestBuilder[WebSocketStreamRequest[T, S]] { override def method(method: Method, uri: Uri): WebSocketStreamRequest[T, S] = copy(method = method, uri = uri) diff --git a/core/src/main/scala/sttp/client4/requestBuilder.scala b/core/src/main/scala/sttp/client4/requestBuilder.scala index a67af32280..0e5eb2590d 100644 --- a/core/src/main/scala/sttp/client4/requestBuilder.scala +++ b/core/src/main/scala/sttp/client4/requestBuilder.scala @@ -40,12 +40,12 @@ trait PartialRequestBuilder[+PR <: PartialRequestBuilder[PR, R], +R] def showBasicSafe(sensitiveQueryParams: Set[String]): String def headers: Seq[Header] - def body: GenericRequestBody[_] + def body: GenericRequestBody[?] /** Description of how the response body should be handled. Needs to be specified upfront so that the response is * always consumed and hence there are no requirements on client code to consume it. */ - def response: ResponseAsDelegate[_, _] + def response: ResponseAsDelegate[?, ?] def options: RequestOptions /** Request-specific attributes which can be used by backends for logging, metrics, etc. Empty by default. */ @@ -120,7 +120,7 @@ trait PartialRequestBuilder[+PR <: PartialRequestBuilder[PR, R], +R] /** Adds the given headers to the headers of this request. If a header with the same name already exists, it's * replaced. */ - def headers(hs: Map[String, String]): PR = headers(hs.map(t => Header(t._1, t._2)).toSeq: _*) + def headers(hs: Map[String, String]): PR = headers(hs.map(t => Header(t._1, t._2)).toSeq*) /** Adds the given headers to the headers of this request. If a header with the same name already exists, it's * replaced. @@ -151,10 +151,10 @@ trait PartialRequestBuilder[+PR <: PartialRequestBuilder[PR, R], +R] def cookie(n: String, v: String): PR = cookies((n, v)) /** Adds the cookies from the given response. Any previously defined cookies are left intact. */ - def cookies(r: Response[_]): PR = cookies(r.cookies.collect { case Right(c) => c }.map(c => (c.name, c.value)): _*) + def cookies(r: Response[?]): PR = cookies(r.cookies.collect { case Right(c) => c }.map(c => (c.name, c.value))*) /** Adds the given cookies. Any previously defined cookies are left intact. */ - def cookies(cs: Iterable[CookieWithMeta]): PR = cookies(cs.map(c => (c.name, c.value)).toSeq: _*) + def cookies(cs: Iterable[CookieWithMeta]): PR = cookies(cs.map(c => (c.name, c.value)).toSeq*) /** Adds the given cookies. Any previously defined cookies are left intact. */ def cookies(nvs: (String, String)*): PR = header( diff --git a/core/src/main/scala/sttp/client4/testing/AbstractBackendStub.scala b/core/src/main/scala/sttp/client4/testing/AbstractBackendStub.scala index 22930d516a..7c93bdae9a 100644 --- a/core/src/main/scala/sttp/client4/testing/AbstractBackendStub.scala +++ b/core/src/main/scala/sttp/client4/testing/AbstractBackendStub.scala @@ -16,18 +16,18 @@ import sttp.model.StatusText abstract class AbstractBackendStub[F[_], P]( _monad: MonadError[F], - matchers: PartialFunction[GenericRequest[_, _], F[Response[StubBody]]], + matchers: PartialFunction[GenericRequest[?, ?], F[Response[StubBody]]], fallback: Option[GenericBackend[F, P]] ) extends GenericBackend[F, P] { type Self - protected def withMatchers(matchers: PartialFunction[GenericRequest[_, _], F[Response[StubBody]]]): Self + protected def withMatchers(matchers: PartialFunction[GenericRequest[?, ?], F[Response[StubBody]]]): Self override def monad: MonadError[F] = _monad /** Specify how the stub backend should respond to requests matching the given predicate. * * Note that the stubs are immutable, and each new specification that is added yields a new stub instance. */ - def whenRequestMatches(p: GenericRequest[_, _] => Boolean): WhenRequest = + def whenRequestMatches(p: GenericRequest[?, ?] => Boolean): WhenRequest = new WhenRequest(p) /** Specify how the stub backend should respond to any request (catch-all). @@ -40,13 +40,13 @@ abstract class AbstractBackendStub[F[_], P]( * * Note that the stubs are immutable, and each new specification that is added yields a new stub instance. */ - def whenRequestMatchesPartial(partial: PartialFunction[GenericRequest[_, _], Response[StubBody]]): Self = { - val wrappedPartial: PartialFunction[GenericRequest[_, _], F[Response[StubBody]]] = + def whenRequestMatchesPartial(partial: PartialFunction[GenericRequest[?, ?], Response[StubBody]]): Self = { + val wrappedPartial: PartialFunction[GenericRequest[?, ?], F[Response[StubBody]]] = partial.andThen((r: Response[StubBody]) => monad.unit(r)) withMatchers(matchers.orElse(wrappedPartial)) } - override def send[T](request: GenericRequest[T, P with Effect[F]]): F[Response[T]] = monad.suspend { + override def send[T](request: GenericRequest[T, P & Effect[F]]): F[Response[T]] = monad.suspend { Try(matchers.lift(request)) match { case Success(Some(response)) => adjustExceptions(request) { @@ -56,7 +56,8 @@ abstract class AbstractBackendStub[F[_], P]( r.body match { case StubBody.Exact(v) => monad.unit(r.copy(body = v.asInstanceOf[T])) case StubBody.Adjust(v) => - monad.map(adjustResponseBody(request.response.delegate, v, r.asInstanceOf[Response[T]])(monad))(b => + implicit val m: MonadError[F] = monad + monad.map(adjustResponseBody(request.response.delegate, v, r.asInstanceOf[Response[T]]))(b => r.copy(body = b) ) } @@ -77,14 +78,14 @@ abstract class AbstractBackendStub[F[_], P]( } } - private def adjustExceptions[T](request: GenericRequest[_, _])(t: => F[T]): F[T] = + private def adjustExceptions[T](request: GenericRequest[?, ?])(t: => F[T]): F[T] = SttpClientException.adjustExceptions(monad)(t)( SttpClientException.defaultExceptionToSttpClientException(request, _) ) override def close(): F[Unit] = monad.unit(()) - class WhenRequest(p: GenericRequest[_, _] => Boolean) { + class WhenRequest(p: GenericRequest[?, ?] => Boolean) { /** Respond with an empty body and the 200 status code */ def thenRespondOk(): Self = thenRespondWithCode(StatusCode.Ok) @@ -116,7 +117,7 @@ abstract class AbstractBackendStub[F[_], P]( def thenRespondExact(body: Any, code: StatusCode): Self = thenRespond(ResponseStub.exact(body, code)) def thenThrow(e: Throwable): Self = { - val m: PartialFunction[GenericRequest[_, _], F[Response[StubBody]]] = { + val m: PartialFunction[GenericRequest[?, ?], F[Response[StubBody]]] = { case r if p(r) => monad.error(e) } withMatchers(matchers.orElse(m)) @@ -124,7 +125,7 @@ abstract class AbstractBackendStub[F[_], P]( /** Response with the given response (lazily evaluated). To create responses, use [[ResponseStub]]. */ def thenRespond[T](resp: => Response[StubBody]): Self = { - val m: PartialFunction[GenericRequest[_, _], F[Response[StubBody]]] = { + val m: PartialFunction[GenericRequest[?, ?], F[Response[StubBody]]] = { case r if p(r) => monad.eval(resp.copy(request = r.onlyMetadata)) } withMatchers(matchers.orElse(m)) @@ -138,7 +139,7 @@ abstract class AbstractBackendStub[F[_], P]( /** Response with the given response, given as an F-effect. To create responses, use [[ResponseStub]]. */ def thenRespondF(resp: => F[Response[StubBody]]): Self = { - val m: PartialFunction[GenericRequest[_, _], F[Response[StubBody]]] = { + val m: PartialFunction[GenericRequest[?, ?], F[Response[StubBody]]] = { case r if p(r) => resp } withMatchers(matchers.orElse(m)) @@ -147,8 +148,8 @@ abstract class AbstractBackendStub[F[_], P]( /** Response with the given response, given as an F-effect, created basing on the received request. To create * responses, use [[ResponseStub]]. */ - def thenRespondF(resp: GenericRequest[_, _] => F[Response[StubBody]]): Self = { - val m: PartialFunction[GenericRequest[_, _], F[Response[StubBody]]] = { + def thenRespondF(resp: GenericRequest[?, ?] => F[Response[StubBody]]): Self = { + val m: PartialFunction[GenericRequest[?, ?], F[Response[StubBody]]] = { case r if p(r) => resp(r) } withMatchers(matchers.orElse(m)) @@ -158,7 +159,7 @@ abstract class AbstractBackendStub[F[_], P]( object AbstractBackendStub { private def adjustResponseBody[F[_], T, U]( - ra: GenericResponseAs[T, _], + ra: GenericResponseAs[T, ?], b: U, meta: ResponseMetadata )(implicit monad: MonadError[F]): F[T] = { @@ -193,7 +194,7 @@ object AbstractBackendStub { case ResponseAsWebSocket(f) => b match { case wss: WebSocketStub[_] => - f.asInstanceOf[(WebSocket[F], ResponseMetadata) => F[T]](wss.build[F](monad), meta) + f.asInstanceOf[(WebSocket[F], ResponseMetadata) => F[T]](wss.build[F], meta) case ws: WebSocket[_] => f.asInstanceOf[(WebSocket[F], ResponseMetadata) => F[T]](ws.asInstanceOf[WebSocket[F]], meta) case _ => @@ -205,7 +206,7 @@ object AbstractBackendStub { } case ResponseAsWebSocketUnsafe() => b match { - case wss: WebSocketStub[_] => wss.build[F](monad).unit.asInstanceOf[F[T]] + case wss: WebSocketStub[_] => wss.build[F].unit.asInstanceOf[F[T]] case ws: WebSocket[_] => ws.asInstanceOf[WebSocket[F]].unit.asInstanceOf[F[T]] case _ => monad.error( diff --git a/core/src/main/scala/sttp/client4/testing/BackendStub.scala b/core/src/main/scala/sttp/client4/testing/BackendStub.scala index c2f2641d6e..3328ca8bae 100644 --- a/core/src/main/scala/sttp/client4/testing/BackendStub.scala +++ b/core/src/main/scala/sttp/client4/testing/BackendStub.scala @@ -23,13 +23,13 @@ import scala.concurrent.ExecutionContext */ class BackendStub[F[_]]( monad: MonadError[F], - matchers: PartialFunction[GenericRequest[_, _], F[Response[StubBody]]], + matchers: PartialFunction[GenericRequest[?, ?], F[Response[StubBody]]], fallback: Option[Backend[F]] ) extends AbstractBackendStub[F, Any](monad, matchers, fallback) with Backend[F] { type Self = BackendStub[F] - override protected def withMatchers(matchers: PartialFunction[GenericRequest[_, _], F[Response[StubBody]]]) = + override protected def withMatchers(matchers: PartialFunction[GenericRequest[?, ?], F[Response[StubBody]]]) = new BackendStub(monad, matchers, fallback) } diff --git a/core/src/main/scala/sttp/client4/testing/RecordingBackend.scala b/core/src/main/scala/sttp/client4/testing/RecordingBackend.scala index e94189bca5..544a72d879 100644 --- a/core/src/main/scala/sttp/client4/testing/RecordingBackend.scala +++ b/core/src/main/scala/sttp/client4/testing/RecordingBackend.scala @@ -10,7 +10,7 @@ import sttp.capabilities.Effect import sttp.client4.wrappers.DelegateBackend trait RecordingBackend { - type RequestAndResponse = (GenericRequest[_, _], Try[Response[_]]) + type RequestAndResponse = (GenericRequest[?, ?], Try[Response[?]]) def allInteractions: List[RequestAndResponse] } @@ -20,12 +20,12 @@ abstract class AbstractRecordingBackend[F[_], P](delegate: GenericBackend[F, P]) private val _allInteractions = new AtomicReference[Vector[RequestAndResponse]](Vector()) - private def addInteraction(request: GenericRequest[_, _], response: Try[Response[_]]): Unit = + private def addInteraction(request: GenericRequest[?, ?], response: Try[Response[?]]): Unit = _allInteractions.updateAndGet(new UnaryOperator[Vector[RequestAndResponse]] { override def apply(t: Vector[RequestAndResponse]): Vector[RequestAndResponse] = t.:+((request, response)) }) - override def send[T](request: GenericRequest[T, P with Effect[F]]): F[Response[T]] = + override def send[T](request: GenericRequest[T, P & Effect[F]]): F[Response[T]] = delegate .send(request) .map { response => @@ -41,18 +41,18 @@ abstract class AbstractRecordingBackend[F[_], P](delegate: GenericBackend[F, P]) } object RecordingBackend { - def apply(delegate: SyncBackend): SyncBackend with RecordingBackend = + def apply(delegate: SyncBackend): SyncBackend & RecordingBackend = new AbstractRecordingBackend(delegate) with SyncBackend {} - def apply[F[_]](delegate: Backend[F]): Backend[F] with RecordingBackend = + def apply[F[_]](delegate: Backend[F]): Backend[F] & RecordingBackend = new AbstractRecordingBackend(delegate) with Backend[F] {} - def apply[F[_]](delegate: WebSocketBackend[F]): WebSocketBackend[F] with RecordingBackend = + def apply[F[_]](delegate: WebSocketBackend[F]): WebSocketBackend[F] & RecordingBackend = new AbstractRecordingBackend(delegate) with WebSocketBackend[F] {} - def apply[F[_], S](delegate: StreamBackend[F, S]): StreamBackend[F, S] with RecordingBackend = + def apply[F[_], S](delegate: StreamBackend[F, S]): StreamBackend[F, S] & RecordingBackend = new AbstractRecordingBackend(delegate) with StreamBackend[F, S] {} - def apply[F[_], S](delegate: WebSocketStreamBackend[F, S]): WebSocketStreamBackend[F, S] with RecordingBackend = + def apply[F[_], S](delegate: WebSocketStreamBackend[F, S]): WebSocketStreamBackend[F, S] & RecordingBackend = new AbstractRecordingBackend(delegate) with WebSocketStreamBackend[F, S] {} } diff --git a/core/src/main/scala/sttp/client4/testing/StreamBackendStub.scala b/core/src/main/scala/sttp/client4/testing/StreamBackendStub.scala index cca5a9b4a5..3ec6aac7aa 100644 --- a/core/src/main/scala/sttp/client4/testing/StreamBackendStub.scala +++ b/core/src/main/scala/sttp/client4/testing/StreamBackendStub.scala @@ -28,14 +28,14 @@ import scala.concurrent.ExecutionContext */ class StreamBackendStub[F[_], S]( monad: MonadError[F], - matchers: PartialFunction[GenericRequest[_, _], F[Response[StubBody]]], + matchers: PartialFunction[GenericRequest[?, ?], F[Response[StubBody]]], fallback: Option[StreamBackend[F, S]] ) extends AbstractBackendStub[F, S](monad, matchers, fallback) with StreamBackend[F, S] { type Self = StreamBackendStub[F, S] override protected def withMatchers( - matchers: PartialFunction[GenericRequest[_, _], F[Response[StubBody]]] + matchers: PartialFunction[GenericRequest[?, ?], F[Response[StubBody]]] ): StreamBackendStub[F, S] = new StreamBackendStub(monad, matchers, fallback) } diff --git a/core/src/main/scala/sttp/client4/testing/SyncBackendStub.scala b/core/src/main/scala/sttp/client4/testing/SyncBackendStub.scala index 42e8aa2e9e..f22f6d06ca 100644 --- a/core/src/main/scala/sttp/client4/testing/SyncBackendStub.scala +++ b/core/src/main/scala/sttp/client4/testing/SyncBackendStub.scala @@ -20,13 +20,13 @@ import sttp.shared.Identity * Predicates can match requests basing on the URI or headers. */ class SyncBackendStub( - matchers: PartialFunction[GenericRequest[_, _], Response[StubBody]], + matchers: PartialFunction[GenericRequest[?, ?], Response[StubBody]], fallback: Option[SyncBackend] ) extends AbstractBackendStub[Identity, Any](IdentityMonad, matchers, fallback) with SyncBackend { type Self = SyncBackendStub - override protected def withMatchers(matchers: PartialFunction[GenericRequest[_, _], Response[StubBody]]) = + override protected def withMatchers(matchers: PartialFunction[GenericRequest[?, ?], Response[StubBody]]) = new SyncBackendStub(matchers, fallback) } diff --git a/core/src/main/scala/sttp/client4/testing/WebSocketBackendStub.scala b/core/src/main/scala/sttp/client4/testing/WebSocketBackendStub.scala index 28d6d4b8fe..f5cef7d8da 100644 --- a/core/src/main/scala/sttp/client4/testing/WebSocketBackendStub.scala +++ b/core/src/main/scala/sttp/client4/testing/WebSocketBackendStub.scala @@ -27,14 +27,14 @@ import sttp.capabilities.WebSockets */ class WebSocketBackendStub[F[_]]( monad: MonadError[F], - matchers: PartialFunction[GenericRequest[_, _], F[Response[StubBody]]], + matchers: PartialFunction[GenericRequest[?, ?], F[Response[StubBody]]], fallback: Option[WebSocketBackend[F]] ) extends AbstractBackendStub[F, WebSockets](monad, matchers, fallback) with WebSocketBackend[F] { type Self = WebSocketBackendStub[F] override protected def withMatchers( - matchers: PartialFunction[GenericRequest[_, _], F[Response[StubBody]]] + matchers: PartialFunction[GenericRequest[?, ?], F[Response[StubBody]]] ): WebSocketBackendStub[F] = new WebSocketBackendStub(monad, matchers, fallback) } diff --git a/core/src/main/scala/sttp/client4/testing/WebSocketStreamBackendStub.scala b/core/src/main/scala/sttp/client4/testing/WebSocketStreamBackendStub.scala index b12c2792c1..302bd6fc9c 100644 --- a/core/src/main/scala/sttp/client4/testing/WebSocketStreamBackendStub.scala +++ b/core/src/main/scala/sttp/client4/testing/WebSocketStreamBackendStub.scala @@ -32,13 +32,13 @@ import sttp.shared.Identity */ class WebSocketStreamBackendStub[F[_], S]( monad: MonadError[F], - matchers: PartialFunction[GenericRequest[_, _], F[Response[StubBody]]], + matchers: PartialFunction[GenericRequest[?, ?], F[Response[StubBody]]], fallback: Option[WebSocketStreamBackend[F, S]] -) extends AbstractBackendStub[F, S with WebSockets](monad, matchers, fallback) +) extends AbstractBackendStub[F, S & WebSockets](monad, matchers, fallback) with WebSocketStreamBackend[F, S] { type Self = WebSocketStreamBackendStub[F, S] override protected def withMatchers( - matchers: PartialFunction[GenericRequest[_, _], F[Response[StubBody]]] + matchers: PartialFunction[GenericRequest[?, ?], F[Response[StubBody]]] ): WebSocketStreamBackendStub[F, S] = new WebSocketStreamBackendStub(monad, matchers, fallback) } diff --git a/core/src/main/scala/sttp/client4/testing/WebSocketStreamConsumer.scala b/core/src/main/scala/sttp/client4/testing/WebSocketStreamConsumer.scala index 15681ed3b8..a2b191ba82 100644 --- a/core/src/main/scala/sttp/client4/testing/WebSocketStreamConsumer.scala +++ b/core/src/main/scala/sttp/client4/testing/WebSocketStreamConsumer.scala @@ -7,7 +7,7 @@ import sttp.ws.WebSocketFrame * when creating a [[BackendStub]]. */ case class WebSocketStreamConsumer[S, Pipe[_, _], F[_]] private ( - consume: Pipe[WebSocketFrame.Data[_], WebSocketFrame] => F[Unit] + consume: Pipe[WebSocketFrame.Data[?], WebSocketFrame] => F[Unit] ) object WebSocketStreamConsumer { @@ -15,7 +15,7 @@ object WebSocketStreamConsumer { trait WebSocketStreamConsumerCreator[F[_]] { def apply[S <: Streams[S]](s: Streams[S])( - consume: s.Pipe[WebSocketFrame.Data[_], WebSocketFrame] => F[Unit] + consume: s.Pipe[WebSocketFrame.Data[?], WebSocketFrame] => F[Unit] ): WebSocketStreamConsumer[S, s.Pipe, F] = new WebSocketStreamConsumer(consume) } } diff --git a/core/src/main/scala/sttp/client4/testing/WebSocketSyncBackendStub.scala b/core/src/main/scala/sttp/client4/testing/WebSocketSyncBackendStub.scala index 0c81ec0331..4c3fcffa6f 100644 --- a/core/src/main/scala/sttp/client4/testing/WebSocketSyncBackendStub.scala +++ b/core/src/main/scala/sttp/client4/testing/WebSocketSyncBackendStub.scala @@ -24,13 +24,13 @@ import sttp.shared.Identity * Predicates can match requests basing on the URI or headers. */ class WebSocketSyncBackendStub( - matchers: PartialFunction[GenericRequest[_, _], Response[StubBody]], + matchers: PartialFunction[GenericRequest[?, ?], Response[StubBody]], fallback: Option[WebSocketSyncBackend] ) extends AbstractBackendStub[Identity, WebSockets](IdentityMonad, matchers, fallback) with WebSocketSyncBackend { type Self = WebSocketSyncBackendStub - override protected def withMatchers(matchers: PartialFunction[GenericRequest[_, _], Response[StubBody]]) = + override protected def withMatchers(matchers: PartialFunction[GenericRequest[?, ?], Response[StubBody]]) = new WebSocketSyncBackendStub(matchers, fallback) } diff --git a/core/src/main/scala/sttp/client4/wrappers/DigestAuthenticationBackend.scala b/core/src/main/scala/sttp/client4/wrappers/DigestAuthenticationBackend.scala index f10954031a..2f956d6dcb 100644 --- a/core/src/main/scala/sttp/client4/wrappers/DigestAuthenticationBackend.scala +++ b/core/src/main/scala/sttp/client4/wrappers/DigestAuthenticationBackend.scala @@ -24,7 +24,7 @@ abstract class DigestAuthenticationBackend[F[_], P] private ( clientNonceGenerator: () => String ) extends DelegateBackend(delegate) { - override def send[T](request: GenericRequest[T, P with Effect[F]]): F[Response[T]] = + override def send[T](request: GenericRequest[T, P & Effect[F]]): F[Response[T]] = delegate .send(request) .flatMap { firstResponse => @@ -45,7 +45,7 @@ abstract class DigestAuthenticationBackend[F[_], P] private ( } private def handleResponse[T]( - request: GenericRequest[T, P with Effect[F]], + request: GenericRequest[T, P & Effect[F]], response: Response[T], digestAttributeKey: AttributeKey[DigestAuthenticator.DigestAuthData], digestAuthenticator: DigestAuthData => DigestAuthenticator @@ -60,16 +60,18 @@ abstract class DigestAuthenticationBackend[F[_], P] private ( } object DigestAuthenticationBackend { - def apply(delegate: SyncBackend): SyncBackend = apply(delegate, DigestAuthenticator.defaultClientNonceGenerator _) - def apply[F[_]](delegate: Backend[F]): Backend[F] = apply(delegate, DigestAuthenticator.defaultClientNonceGenerator _) + def apply(delegate: SyncBackend): SyncBackend = + apply(delegate, () => DigestAuthenticator.defaultClientNonceGenerator()) + def apply[F[_]](delegate: Backend[F]): Backend[F] = + apply(delegate, () => DigestAuthenticator.defaultClientNonceGenerator()) def apply[F[_]](delegate: WebSocketBackend[F]): WebSocketBackend[F] = - apply(delegate, DigestAuthenticator.defaultClientNonceGenerator _) + apply(delegate, () => DigestAuthenticator.defaultClientNonceGenerator()) def apply[F[_]](delegate: WebSocketSyncBackend): WebSocketSyncBackend = - apply(delegate, DigestAuthenticator.defaultClientNonceGenerator _) + apply(delegate, () => DigestAuthenticator.defaultClientNonceGenerator()) def apply[F[_], S](delegate: StreamBackend[F, S]): StreamBackend[F, S] = - apply(delegate, DigestAuthenticator.defaultClientNonceGenerator _) + apply(delegate, () => DigestAuthenticator.defaultClientNonceGenerator()) def apply[F[_], S](delegate: WebSocketStreamBackend[F, S]): WebSocketStreamBackend[F, S] = - apply(delegate, DigestAuthenticator.defaultClientNonceGenerator _) + apply(delegate, () => DigestAuthenticator.defaultClientNonceGenerator()) def apply(delegate: SyncBackend, clientNonceGenerator: () => String): SyncBackend = new DigestAuthenticationBackend(delegate, clientNonceGenerator) with SyncBackend {} def apply[F[_]](delegate: Backend[F], clientNonceGenerator: () => String): Backend[F] = diff --git a/core/src/main/scala/sttp/client4/wrappers/FollowRedirectsBackend.scala b/core/src/main/scala/sttp/client4/wrappers/FollowRedirectsBackend.scala index 7223585342..859ca352ed 100644 --- a/core/src/main/scala/sttp/client4/wrappers/FollowRedirectsBackend.scala +++ b/core/src/main/scala/sttp/client4/wrappers/FollowRedirectsBackend.scala @@ -11,7 +11,7 @@ abstract class FollowRedirectsBackend[F[_], P] private ( config: FollowRedirectsConfig ) extends DelegateBackend(delegate) { - type R = P with Effect[F] + type R = P & Effect[F] override def send[T](request: GenericRequest[T, R]): F[Response[T]] = sendWithCounter(request, 0) @@ -55,7 +55,7 @@ abstract class FollowRedirectsBackend[F[_], P] private ( request.attribute(CookieStorage.attributeKey) match { case Some(storage) => val cookies = storage.cookiesFor(request.uri) - if (cookies.isEmpty) request else request.cookies(cookies: _*) + if (cookies.isEmpty) request else request.cookies(cookies*) case None => request } diff --git a/core/src/main/scala/sttp/client4/wrappers/MappedEffectBackend.scala b/core/src/main/scala/sttp/client4/wrappers/MappedEffectBackend.scala index 59b22c36bc..a86dc8e20b 100644 --- a/core/src/main/scala/sttp/client4/wrappers/MappedEffectBackend.scala +++ b/core/src/main/scala/sttp/client4/wrappers/MappedEffectBackend.scala @@ -19,7 +19,7 @@ abstract class MappedEffectBackend[F[_], G[_], P]( g: FunctionK[G, F], m: MonadError[G] ) extends GenericBackend[G, P] { - override def send[T](request: GenericRequest[T, P with Effect[G]]): G[Response[T]] = + override def send[T](request: GenericRequest[T, P & Effect[G]]): G[Response[T]] = f(backend.send(MapEffect[G, F, T, P](request, g, f, m, backend.monad))) override def close(): G[Unit] = f(backend.close()) diff --git a/core/src/main/scala/sttp/client4/wrappers/ResolveRelativeUrisBackend.scala b/core/src/main/scala/sttp/client4/wrappers/ResolveRelativeUrisBackend.scala index 36c2238cba..0be6cd0dd3 100644 --- a/core/src/main/scala/sttp/client4/wrappers/ResolveRelativeUrisBackend.scala +++ b/core/src/main/scala/sttp/client4/wrappers/ResolveRelativeUrisBackend.scala @@ -18,7 +18,7 @@ import sttp.shared.Identity abstract class ResolveRelativeUrisBackend[F[_], P](delegate: GenericBackend[F, P], resolve: Uri => F[Uri]) extends DelegateBackend(delegate) { - override def send[T](request: GenericRequest[T, P with Effect[F]]): F[Response[T]] = { + override def send[T](request: GenericRequest[T, P & Effect[F]]): F[Response[T]] = { val request2 = if (request.uri.isRelative) { resolve(request.uri).map { uri2 => request.method(method = request.method, uri = uri2) diff --git a/core/src/main/scala/sttp/client4/ws/SyncWebSocket.scala b/core/src/main/scala/sttp/client4/ws/SyncWebSocket.scala index a08e714910..65ed055e66 100644 --- a/core/src/main/scala/sttp/client4/ws/SyncWebSocket.scala +++ b/core/src/main/scala/sttp/client4/ws/SyncWebSocket.scala @@ -47,7 +47,7 @@ class SyncWebSocket(val delegate: WebSocket[Identity]) { * @param pongOnPing * Should a [[WebSocketFrame.Pong]] be sent when a [[WebSocketFrame.Ping]] is received. */ - def receiveDataFrame(pongOnPing: Boolean = true): WebSocketFrame.Data[_] = delegate.receiveDataFrame(pongOnPing) + def receiveDataFrame(pongOnPing: Boolean = true): WebSocketFrame.Data[?] = delegate.receiveDataFrame(pongOnPing) /** Receive a single text data frame, ignoring others. The frame might be a fragment. To receive whole messages, use * [[receiveText]]. Will throw [[WebSocketClosed]] if the web socket is closed, or if a close frame is received. diff --git a/core/src/main/scalajs/sttp/client4/PartialRequestExtensions.scala b/core/src/main/scalajs/sttp/client4/PartialRequestExtensions.scala index 0c74e80937..9826cc15ec 100644 --- a/core/src/main/scalajs/sttp/client4/PartialRequestExtensions.scala +++ b/core/src/main/scalajs/sttp/client4/PartialRequestExtensions.scala @@ -3,7 +3,7 @@ package sttp.client4 import sttp.client4.internal.SttpFile import org.scalajs.dom.File -trait PartialRequestExtensions[+R <: PartialRequestBuilder[R, _]] { self: R => +trait PartialRequestExtensions[+R <: PartialRequestBuilder[R, ?]] { self: R => /** If content type is not yet specified, will be set to `application/octet-stream`. * diff --git a/core/src/main/scalajs/sttp/client4/SttpClientExceptionExtensions.scala b/core/src/main/scalajs/sttp/client4/SttpClientExceptionExtensions.scala index 8512131d86..07499180be 100644 --- a/core/src/main/scalajs/sttp/client4/SttpClientExceptionExtensions.scala +++ b/core/src/main/scalajs/sttp/client4/SttpClientExceptionExtensions.scala @@ -9,7 +9,7 @@ import sttp.client4.SttpClientException.ResponseHandlingException trait SttpClientExceptionExtensions { @tailrec - final def defaultExceptionToSttpClientException(request: GenericRequest[_, _], e: Exception): Option[Exception] = + final def defaultExceptionToSttpClientException(request: GenericRequest[?, ?], e: Exception): Option[Exception] = e match { case e: java.net.MalformedURLException => Some(new ConnectException(request, e)) case e: java.net.URISyntaxException => Some(new ConnectException(request, e)) diff --git a/core/src/main/scalajs/sttp/client4/fetch/AbstractFetchBackend.scala b/core/src/main/scalajs/sttp/client4/fetch/AbstractFetchBackend.scala index 37720a111b..e56636878b 100644 --- a/core/src/main/scalajs/sttp/client4/fetch/AbstractFetchBackend.scala +++ b/core/src/main/scalajs/sttp/client4/fetch/AbstractFetchBackend.scala @@ -63,20 +63,20 @@ abstract class AbstractFetchBackend[F[_], S <: Streams[S]]( options: FetchOptions, customizeRequest: FetchRequest => FetchRequest, _monad: MonadError[F] -) extends GenericBackend[F, S with WebSockets] +) extends GenericBackend[F, S & WebSockets] with WebSocketBackend[F] { override implicit def monad: MonadError[F] = _monad val streams: Streams[S] - type R = S with WebSockets with Effect[F] + type R = S & WebSockets & Effect[F] override def send[T](request: GenericRequest[T, R]): F[Response[T]] = adjustExceptions(request) { if (request.isWebSocket) sendWebSocket(request) else sendRegular(request) } - private def adjustExceptions[T](request: GenericRequest[_, _])(t: => F[T]): F[T] = + private def adjustExceptions[T](request: GenericRequest[?, ?])(t: => F[T]): F[T] = SttpClientException.adjustExceptions(monad)(t)( SttpClientException.defaultExceptionToSttpClientException(request, _) ) @@ -322,7 +322,7 @@ abstract class AbstractFetchBackend[F[_], S <: Streams[S]]( handleResponseAsStream(response) override protected def handleWS[T]( - responseAs: GenericWebSocketResponseAs[T, _], + responseAs: GenericWebSocketResponseAs[T, ?], meta: ResponseMetadata, ws: WebSocket[F] ): F[T] = @@ -331,7 +331,7 @@ abstract class AbstractFetchBackend[F[_], S <: Streams[S]]( f.asInstanceOf[(WebSocket[F], ResponseMetadata) => F[T]].apply(ws, meta) case ResponseAsWebSocketUnsafe() => ws.unit.asInstanceOf[F[T]] case ResponseAsWebSocketStream(_, pipe) => - compileWebSocketPipe(ws, pipe.asInstanceOf[streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame]]) + compileWebSocketPipe(ws, pipe.asInstanceOf[streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame]]) } override protected def cleanupWhenNotAWebSocket(response: FetchResponse, e: NotAWebSocketException): F[Unit] = @@ -345,7 +345,7 @@ abstract class AbstractFetchBackend[F[_], S <: Streams[S]]( protected def compileWebSocketPipe( ws: WebSocket[F], - pipe: streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] + pipe: streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] ): F[Unit] override def close(): F[Unit] = monad.unit(()) diff --git a/core/src/main/scalajvm/sttp/client4/PartialRequestExtensions.scala b/core/src/main/scalajvm/sttp/client4/PartialRequestExtensions.scala index 1281ef3570..6861a7e853 100644 --- a/core/src/main/scalajvm/sttp/client4/PartialRequestExtensions.scala +++ b/core/src/main/scalajvm/sttp/client4/PartialRequestExtensions.scala @@ -5,7 +5,7 @@ import java.nio.file.Path import sttp.client4.internal.SttpFile -trait PartialRequestExtensions[+R <: PartialRequestBuilder[R, _]] { self: R => +trait PartialRequestExtensions[+R <: PartialRequestBuilder[R, ?]] { self: R => /** If content type is not yet specified, will be set to `application/octet-stream`. * diff --git a/core/src/main/scalajvm/sttp/client4/SttpClientExceptionExtensions.scala b/core/src/main/scalajvm/sttp/client4/SttpClientExceptionExtensions.scala index 792e77e01d..21425b9dc6 100644 --- a/core/src/main/scalajvm/sttp/client4/SttpClientExceptionExtensions.scala +++ b/core/src/main/scalajvm/sttp/client4/SttpClientExceptionExtensions.scala @@ -9,7 +9,7 @@ import sttp.capabilities.StreamMaxLengthExceededException trait SttpClientExceptionExtensions { @tailrec - final def defaultExceptionToSttpClientException(request: GenericRequest[_, _], e: Exception): Option[Exception] = + final def defaultExceptionToSttpClientException(request: GenericRequest[?, ?], e: Exception): Option[Exception] = e match { case e: java.net.ConnectException => Some(new ConnectException(request, e)) case e: java.net.UnknownHostException => Some(new ConnectException(request, e)) diff --git a/core/src/main/scalajvm/sttp/client4/compression/GZIPCompressingInputStream.scala b/core/src/main/scalajvm/sttp/client4/compression/GZIPCompressingInputStream.scala index 10ef537f91..4cdc6ea9b6 100644 --- a/core/src/main/scalajvm/sttp/client4/compression/GZIPCompressingInputStream.scala +++ b/core/src/main/scalajvm/sttp/client4/compression/GZIPCompressingInputStream.scala @@ -37,7 +37,7 @@ class GZIPCompressingInputStream( deflater.setLevel(compressionLevel) private val crc = new CRC32() - private var trailer: ByteArrayInputStream = _ + private var trailer: ByteArrayInputStream = null private val header = new ByteArrayInputStream(HEADER_DATA) private var deflationBuffer: Array[Byte] = new Array[Byte](INITIAL_BUFFER_SIZE) diff --git a/core/src/main/scalajvm/sttp/client4/httpclient/HttpClientAsyncBackend.scala b/core/src/main/scalajvm/sttp/client4/httpclient/HttpClientAsyncBackend.scala index 6b66818c8b..754a986152 100644 --- a/core/src/main/scalajvm/sttp/client4/httpclient/HttpClientAsyncBackend.scala +++ b/core/src/main/scalajvm/sttp/client4/httpclient/HttpClientAsyncBackend.scala @@ -43,7 +43,7 @@ abstract class HttpClientAsyncBackend[F[_], S <: Streams[S], BH, B]( closeClient: Boolean, customizeRequest: HttpRequest => HttpRequest, compressionHandlers: CompressionHandlers[S, B] -) extends HttpClientBackend[F, S, S with WebSockets, B](client, closeClient, compressionHandlers) +) extends HttpClientBackend[F, S, S & WebSockets, B](client, closeClient, compressionHandlers) with WebSocketBackend[F] { protected def createSimpleQueue[T]: F[SimpleQueue[F, T]] protected def createSequencer: F[Sequencer[F]] diff --git a/core/src/main/scalajvm/sttp/client4/httpclient/HttpClientBackend.scala b/core/src/main/scalajvm/sttp/client4/httpclient/HttpClientBackend.scala index 001e5dd6a5..364def4108 100644 --- a/core/src/main/scalajvm/sttp/client4/httpclient/HttpClientBackend.scala +++ b/core/src/main/scalajvm/sttp/client4/httpclient/HttpClientBackend.scala @@ -46,7 +46,7 @@ abstract class HttpClientBackend[F[_], S <: Streams[S], P, B]( with Backend[F] { val streams: Streams[S] - type R = P with Effect[F] + type R = P & Effect[F] override def send[T](request: GenericRequest[T, R]): F[Response[T]] = adjustExceptions(request) { @@ -57,7 +57,7 @@ abstract class HttpClientBackend[F[_], S <: Streams[S], P, B]( protected def sendWebSocket[T](request: GenericRequest[T, R]): F[Response[T]] - private def adjustExceptions[T](request: GenericRequest[_, _])(t: => F[T]): F[T] = + private def adjustExceptions[T](request: GenericRequest[?, ?])(t: => F[T]): F[T] = SttpClientException.adjustExceptions(monad)(t)( SttpClientException.defaultExceptionToSttpClientException(request, _) ) @@ -106,7 +106,7 @@ abstract class HttpClientBackend[F[_], S <: Streams[S], P, B]( private implicit val _monad: MonadError[F] = monad private[client4] def readResponse[T]( - res: HttpResponse[_], + res: HttpResponse[?], resBody: Either[B, WebSocket[F]], request: GenericRequest[T, R] ): F[Response[T]] = { @@ -157,7 +157,7 @@ abstract class HttpClientBackend[F[_], S <: Streams[S], P, B]( val wsBuilder = wsSubProtocols match { case Nil => client.newWebSocketBuilder() case head :: Nil => client.newWebSocketBuilder().subprotocols(head) - case head :: tail => client.newWebSocketBuilder().subprotocols(head, tail: _*) + case head :: tail => client.newWebSocketBuilder().subprotocols(head, tail*) } client .connectTimeout() diff --git a/core/src/main/scalajvm/sttp/client4/httpclient/HttpClientFutureBackend.scala b/core/src/main/scalajvm/sttp/client4/httpclient/HttpClientFutureBackend.scala index 803a635480..6174d31427 100644 --- a/core/src/main/scalajvm/sttp/client4/httpclient/HttpClientFutureBackend.scala +++ b/core/src/main/scalajvm/sttp/client4/httpclient/HttpClientFutureBackend.scala @@ -63,7 +63,7 @@ class HttpClientFutureBackend private ( override implicit def monad: MonadError[Future] = new FutureMonad() override def compileWebSocketPipe( ws: WebSocket[Future], - pipe: streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] + pipe: streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] ): Future[Unit] = pipe } diff --git a/core/src/main/scalajvm/sttp/client4/httpclient/HttpClientSyncBackend.scala b/core/src/main/scalajvm/sttp/client4/httpclient/HttpClientSyncBackend.scala index fc77dac3a8..46eb0d372e 100644 --- a/core/src/main/scalajvm/sttp/client4/httpclient/HttpClientSyncBackend.scala +++ b/core/src/main/scalajvm/sttp/client4/httpclient/HttpClientSyncBackend.scala @@ -150,7 +150,7 @@ class HttpClientSyncBackend private ( override implicit def monad: MonadError[Identity] = IdentityMonad override def compileWebSocketPipe( ws: WebSocket[Identity], - pipe: streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] + pipe: streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] ): Identity[Unit] = pipe } diff --git a/core/src/main/scalajvm/sttp/client4/httpurlconnection/HttpURLConnectionBackend.scala b/core/src/main/scalajvm/sttp/client4/httpurlconnection/HttpURLConnectionBackend.scala index 46e709695f..6e2171769e 100644 --- a/core/src/main/scalajvm/sttp/client4/httpurlconnection/HttpURLConnectionBackend.scala +++ b/core/src/main/scalajvm/sttp/client4/httpurlconnection/HttpURLConnectionBackend.scala @@ -48,7 +48,7 @@ class HttpURLConnectionBackend private ( openConnection: (URL, Option[java.net.Proxy]) => URLConnection, compressionHandlers: CompressionHandlers[Any, InputStream] ) extends SyncBackend { - type R = Any with Effect[Identity] + type R = Any & Effect[Identity] override def send[T](r: GenericRequest[T, R]): Response[T] = adjustExceptions(r) { @@ -114,7 +114,7 @@ class HttpURLConnectionBackend private ( private def writeBody( body: GenericRequestBody[R], - r: GenericRequest[_, R], + r: GenericRequest[?, R], c: HttpURLConnection ): Option[OutputStream] = body match { @@ -166,7 +166,7 @@ class HttpURLConnectionBackend private ( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".toCharArray private def setMultipartBody( - r: GenericRequest[_, R], + r: GenericRequest[?, R], mp: BasicMultipartBody, c: HttpURLConnection ): Option[OutputStream] = { @@ -292,7 +292,7 @@ class HttpURLConnectionBackend private ( throw new IllegalStateException() override protected def regularAsInputStream(response: InputStream): Identity[InputStream] = response override protected def handleWS[T]( - responseAs: GenericWebSocketResponseAs[T, _], + responseAs: GenericWebSocketResponseAs[T, ?], meta: ResponseMetadata, ws: Nothing ): Identity[T] = ws @@ -313,7 +313,7 @@ class HttpURLConnectionBackend private ( case Some(encoding) => Decompressor.decompressIfPossible(is, encoding, compressionHandlers.decompressors) } - private def adjustExceptions[T](request: GenericRequest[_, R])(t: => T): T = + private def adjustExceptions[T](request: GenericRequest[?, R])(t: => T): T = SttpClientException.adjustExceptions(monad)(t)( SttpClientException.defaultExceptionToSttpClientException(request, _) ) diff --git a/core/src/main/scalajvm/sttp/client4/internal/httpclient/BodyFromHttpClient.scala b/core/src/main/scalajvm/sttp/client4/internal/httpclient/BodyFromHttpClient.scala index 59d195f46f..5bb54082b3 100644 --- a/core/src/main/scalajvm/sttp/client4/internal/httpclient/BodyFromHttpClient.scala +++ b/core/src/main/scalajvm/sttp/client4/internal/httpclient/BodyFromHttpClient.scala @@ -11,22 +11,22 @@ import sttp.ws.{WebSocket, WebSocketFrame} private[client4] trait BodyFromHttpClient[F[_], S, B] { val streams: Streams[S] implicit def monad: MonadError[F] - def compileWebSocketPipe(ws: WebSocket[F], pipe: streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame]): F[Unit] + def compileWebSocketPipe(ws: WebSocket[F], pipe: streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame]): F[Unit] def apply[T]( response: Either[B, WebSocket[F]], - responseAs: ResponseAsDelegate[T, _], + responseAs: ResponseAsDelegate[T, ?], responseMetadata: ResponseMetadata ): F[T] = bodyFromResponseAs(responseAs, responseMetadata, response) protected def bodyFromResponseAs: BodyFromResponseAs[F, B, WebSocket[F], streams.BinaryStream] - protected def bodyFromWs[T](r: GenericWebSocketResponseAs[T, _], ws: WebSocket[F], meta: ResponseMetadata): F[T] = + protected def bodyFromWs[T](r: GenericWebSocketResponseAs[T, ?], ws: WebSocket[F], meta: ResponseMetadata): F[T] = r match { case ResponseAsWebSocket(f) => f.asInstanceOf[(WebSocket[F], ResponseMetadata) => F[T]](ws, meta).ensure(ws.close()) case ResponseAsWebSocketUnsafe() => ws.unit.asInstanceOf[F[T]] case ResponseAsWebSocketStream(_, p) => - compileWebSocketPipe(ws, p.asInstanceOf[streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame]]) + compileWebSocketPipe(ws, p.asInstanceOf[streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame]]) } } diff --git a/core/src/main/scalajvm/sttp/client4/internal/httpclient/BodyToHttpClient.scala b/core/src/main/scalajvm/sttp/client4/internal/httpclient/BodyToHttpClient.scala index c4405f8e12..49af0b4d17 100644 --- a/core/src/main/scalajvm/sttp/client4/internal/httpclient/BodyToHttpClient.scala +++ b/core/src/main/scalajvm/sttp/client4/internal/httpclient/BodyToHttpClient.scala @@ -38,7 +38,7 @@ private[client4] trait BodyToHttpClient[F[_], S, R] { case StreamBody(s) => streamToPublisher(s.asInstanceOf[streams.BinaryStream]) case m: MultipartBody[_] => val baseContentType = contentType.getOrElse("multipart/form-data") - val (body, boundary) = multiPartBodyBuilder(m.parts)(monad) + val (body, boundary) = multiPartBodyBuilder(m.parts) builder.header(HeaderNames.ContentType, s"$baseContentType; boundary=$boundary") body } @@ -61,7 +61,7 @@ private[client4] trait BodyToHttpClient[F[_], S, R] { private def withKnownContentLength(delegate: HttpRequest.BodyPublisher, cl: Long): HttpRequest.BodyPublisher = new HttpRequest.BodyPublisher { override def contentLength(): Long = cl - override def subscribe(subscriber: Flow.Subscriber[_ >: ByteBuffer]): Unit = delegate.subscribe(subscriber) + override def subscribe(subscriber: Flow.Subscriber[? >: ByteBuffer]): Unit = delegate.subscribe(subscriber) } private def withCallback( @@ -70,7 +70,7 @@ private[client4] trait BodyToHttpClient[F[_], S, R] { ): HttpRequest.BodyPublisher = new HttpRequest.BodyPublisher { override def contentLength(): Long = delegate.contentLength() - override def subscribe(subscriber: Flow.Subscriber[_ >: ByteBuffer]): Unit = { + override def subscribe(subscriber: Flow.Subscriber[? >: ByteBuffer]): Unit = { delegate.subscribe(new Flow.Subscriber[ByteBuffer] { override def onSubscribe(subscription: Subscription): Unit = { runCallbackSafe { diff --git a/core/src/main/scalajvm/sttp/client4/internal/httpclient/DelegatingWebSocketListener.scala b/core/src/main/scalajvm/sttp/client4/internal/httpclient/DelegatingWebSocketListener.scala index 5272fe84f1..4d0b12ef3b 100644 --- a/core/src/main/scalajvm/sttp/client4/internal/httpclient/DelegatingWebSocketListener.scala +++ b/core/src/main/scalajvm/sttp/client4/internal/httpclient/DelegatingWebSocketListener.scala @@ -20,19 +20,19 @@ private[client4] class DelegatingWebSocketListener[WS_RESULT]( delegate.onOpen(webSocket) } - override def onText(webSocket: WebSocket, data: CharSequence, last: Boolean): CompletionStage[_] = + override def onText(webSocket: WebSocket, data: CharSequence, last: Boolean): CompletionStage[?] = delegate.onText(webSocket, data, last) - override def onBinary(webSocket: WebSocket, data: ByteBuffer, last: Boolean): CompletionStage[_] = + override def onBinary(webSocket: WebSocket, data: ByteBuffer, last: Boolean): CompletionStage[?] = delegate.onBinary(webSocket, data, last) - override def onPing(webSocket: WebSocket, message: ByteBuffer): CompletionStage[_] = + override def onPing(webSocket: WebSocket, message: ByteBuffer): CompletionStage[?] = delegate.onPing(webSocket, message) - override def onPong(webSocket: WebSocket, message: ByteBuffer): CompletionStage[_] = + override def onPong(webSocket: WebSocket, message: ByteBuffer): CompletionStage[?] = delegate.onPong(webSocket, message) - override def onClose(webSocket: WebSocket, statusCode: Int, reason: String): CompletionStage[_] = + override def onClose(webSocket: WebSocket, statusCode: Int, reason: String): CompletionStage[?] = delegate.onClose(webSocket, statusCode, reason) override def onError(webSocket: WebSocket, error: Throwable): Unit = { if (!initialised.getAndSet(true)) { diff --git a/core/src/main/scalajvm/sttp/client4/internal/httpclient/InputStreamBodyFromHttpClient.scala b/core/src/main/scalajvm/sttp/client4/internal/httpclient/InputStreamBodyFromHttpClient.scala index 2fa5e9634b..795ee7b493 100644 --- a/core/src/main/scalajvm/sttp/client4/internal/httpclient/InputStreamBodyFromHttpClient.scala +++ b/core/src/main/scalajvm/sttp/client4/internal/httpclient/InputStreamBodyFromHttpClient.scala @@ -44,7 +44,7 @@ private[client4] trait InputStreamBodyFromHttpClient[F[_], S] extends BodyFromHt override protected def regularAsInputStream(response: InputStream): F[InputStream] = monad.unit(response) override protected def handleWS[T]( - responseAs: GenericWebSocketResponseAs[T, _], + responseAs: GenericWebSocketResponseAs[T, ?], meta: ResponseMetadata, ws: WebSocket[F] ): F[T] = bodyFromWs(responseAs, ws, meta) diff --git a/core/src/main/scalajvm/sttp/client4/internal/httpclient/MultipartBodyBuilder.scala b/core/src/main/scalajvm/sttp/client4/internal/httpclient/MultipartBodyBuilder.scala index 8cdfdbf321..6fff7e912d 100644 --- a/core/src/main/scalajvm/sttp/client4/internal/httpclient/MultipartBodyBuilder.scala +++ b/core/src/main/scalajvm/sttp/client4/internal/httpclient/MultipartBodyBuilder.scala @@ -23,13 +23,13 @@ import scala.collection.JavaConverters._ trait MultipartBodyBuilder[BinaryStream, F[_]] { def apply( - parts: Seq[Part[GenericRequestBody[_]]] + parts: Seq[Part[GenericRequestBody[?]]] )(implicit m: MonadError[F]): (F[HttpRequest.BodyPublisher], String) } trait NonStreamMultipartBodyBuilder[BinaryStream, F[_]] extends MultipartBodyBuilder[BinaryStream, F] { override def apply( - parts: Seq[Part[GenericRequestBody[_]]] + parts: Seq[Part[GenericRequestBody[?]]] )(implicit m: MonadError[F]): (F[HttpRequest.BodyPublisher], String) = { val multipartBuilder = new MultiPartBodyPublisher() parts.foreach { p => @@ -72,7 +72,7 @@ trait StreamMultipartBodyBuilder[BinaryStream, F[_]] extends MultipartBodyBuilde def inputStreamToStream(stream: InputStream): BinaryStream override def apply( - parts: Seq[Part[GenericRequestBody[_]]] + parts: Seq[Part[GenericRequestBody[?]]] )(implicit m: MonadError[F]): (F[HttpRequest.BodyPublisher], String) = { val boundary: String = UUID.randomUUID.toString val resultStream = parts.foldLeft(byteArrayToStream(Array.empty[Byte])) { (accumulatedStream, part) => diff --git a/core/src/main/scalajvm/sttp/client4/internal/httpclient/WebSocketImpl.scala b/core/src/main/scalajvm/sttp/client4/internal/httpclient/WebSocketImpl.scala index 164f11a287..6aaba6e15e 100644 --- a/core/src/main/scalajvm/sttp/client4/internal/httpclient/WebSocketImpl.scala +++ b/core/src/main/scalajvm/sttp/client4/internal/httpclient/WebSocketImpl.scala @@ -75,27 +75,27 @@ private[client4] class AddToQueueListener[F[_]]( webSocket.request(1) } - override def onText(webSocket: JWebSocket, data: CharSequence, last: Boolean): CompletionStage[_] = { + override def onText(webSocket: JWebSocket, data: CharSequence, last: Boolean): CompletionStage[?] = { onFrame(WebSocketFrame.Text(data.toString, last, None)) null } - override def onBinary(webSocket: JWebSocket, data: ByteBuffer, last: Boolean): CompletionStage[_] = { + override def onBinary(webSocket: JWebSocket, data: ByteBuffer, last: Boolean): CompletionStage[?] = { onFrame(WebSocketFrame.Binary(data.safeRead(), last, None)) null } - override def onPing(webSocket: JWebSocket, message: ByteBuffer): CompletionStage[_] = { + override def onPing(webSocket: JWebSocket, message: ByteBuffer): CompletionStage[?] = { onFrame(WebSocketFrame.Ping(message.safeRead())) null } - override def onPong(webSocket: JWebSocket, message: ByteBuffer): CompletionStage[_] = { + override def onPong(webSocket: JWebSocket, message: ByteBuffer): CompletionStage[?] = { onFrame(WebSocketFrame.Pong(message.safeRead())) null } - override def onClose(webSocket: JWebSocket, statusCode: Int, reason: String): CompletionStage[_] = { + override def onClose(webSocket: JWebSocket, statusCode: Int, reason: String): CompletionStage[?] = { isOpen.set(false) queue.offer(WebSocketEvent.Frame(WebSocketFrame.Close(statusCode, reason))) super.onClose(webSocket, statusCode, reason) diff --git a/core/src/main/scalanative/sttp/client4/PartialRequestExtensions.scala b/core/src/main/scalanative/sttp/client4/PartialRequestExtensions.scala index 93f1b21b99..f4adc480c0 100644 --- a/core/src/main/scalanative/sttp/client4/PartialRequestExtensions.scala +++ b/core/src/main/scalanative/sttp/client4/PartialRequestExtensions.scala @@ -5,7 +5,7 @@ import java.nio.file.Path import sttp.client4.internal._ -trait PartialRequestExtensions[+R <: PartialRequestBuilder[R, _]] { self: R => +trait PartialRequestExtensions[+R <: PartialRequestBuilder[R, ?]] { self: R => /** If content type is not yet specified, will be set to `application/octet-stream`. * diff --git a/core/src/main/scalanative/sttp/client4/SttpClientExceptionExtensions.scala b/core/src/main/scalanative/sttp/client4/SttpClientExceptionExtensions.scala index 6e7f85d053..7255dbd870 100644 --- a/core/src/main/scalanative/sttp/client4/SttpClientExceptionExtensions.scala +++ b/core/src/main/scalanative/sttp/client4/SttpClientExceptionExtensions.scala @@ -7,7 +7,7 @@ import scala.annotation.tailrec trait SttpClientExceptionExtensions { @tailrec - final def defaultExceptionToSttpClientException(request: GenericRequest[_, _], e: Exception): Option[Exception] = + final def defaultExceptionToSttpClientException(request: GenericRequest[?, ?], e: Exception): Option[Exception] = e match { case e: java.net.ConnectException => Some(new ConnectException(request, e)) case e: java.net.UnknownHostException => Some(new ConnectException(request, e)) diff --git a/core/src/main/scalanative/sttp/client4/curl/AbstractCurlBackend.scala b/core/src/main/scalanative/sttp/client4/curl/AbstractCurlBackend.scala index da29eeb7b6..7bcc312a2a 100644 --- a/core/src/main/scalanative/sttp/client4/curl/AbstractCurlBackend.scala +++ b/core/src/main/scalanative/sttp/client4/curl/AbstractCurlBackend.scala @@ -34,7 +34,7 @@ abstract class AbstractCurlBackend[F[_]](_monad: MonadError[F], verbose: Boolean /** Same as [[performCurl]], but also checks and throws runtime exceptions on bad [[CurlCode]]s. */ private final def perform(c: CurlHandle) = performCurl(c).flatMap(lift) - type R = Any with Effect[F] + type R = Any & Effect[F] override def close(): F[Unit] = monad.unit(()) @@ -97,7 +97,7 @@ abstract class AbstractCurlBackend[F[_]](_monad: MonadError[F], verbose: Boolean return monad.error(new UnsupportedOperationException("Attributes are not supported")) } - val reqHeaders = collection.mutable.ListBuffer[Header](request.headers: _*) + val reqHeaders = collection.mutable.ListBuffer[Header](request.headers*) request.body match { case _: MultipartBody[_] => @@ -133,10 +133,10 @@ abstract class AbstractCurlBackend[F[_]](_monad: MonadError[F], verbose: Boolean } } - Context.evaluateUsing(ctx => perform(ctx)) + Context.evaluateUsing { implicit ctx => perform } } - private def adjustExceptions[T](request: GenericRequest[_, _])(t: => F[T]): F[T] = + private def adjustExceptions[T](request: GenericRequest[?, ?])(t: => F[T]): F[T] = SttpClientException.adjustExceptions(monad)(t)( SttpClientException.defaultExceptionToSttpClientException(request, _) ) @@ -220,7 +220,7 @@ abstract class AbstractCurlBackend[F[_]](_monad: MonadError[F], verbose: Boolean * MappedResponseAs, ResponseAsFromMetadata conditions, and ResponseAsBoth. Returns true if ANY branch might * produce an InputStream response. */ - def containsInputStreamResponse(delegate: GenericResponseAs[_, _]): Boolean = + def containsInputStreamResponse(delegate: GenericResponseAs[?, ?]): Boolean = delegate match { case ResponseAsInputStream(_) | ResponseAsInputStreamUnsafe => true case MappedResponseAs(raw, _, _) => containsInputStreamResponse(raw) @@ -411,16 +411,16 @@ abstract class AbstractCurlBackend[F[_]](_monad: MonadError[F], verbose: Boolean * evaluating metadata conditions along the way. */ private def resolveResponseAs[T]( - delegate: GenericResponseAs[T, _], + delegate: GenericResponseAs[T, ?], meta: ResponseMetadata - ): GenericResponseAs[_, _] = delegate match { + ): GenericResponseAs[?, ?] = delegate match { case rfm: ResponseAsFromMetadata[_, _] => resolveResponseAs(rfm(meta), meta) case MappedResponseAs(raw, _, _) => resolveResponseAs(raw, meta) case other => other } /** Checks whether a resolved (leaf) response type is a direct InputStream response. */ - private def isDirectInputStreamResponse(resolved: GenericResponseAs[_, _]): Boolean = + private def isDirectInputStreamResponse(resolved: GenericResponseAs[?, ?]): Boolean = resolved match { case ResponseAsInputStream(_) | ResponseAsInputStreamUnsafe => true case _ => false @@ -431,7 +431,7 @@ abstract class AbstractCurlBackend[F[_]](_monad: MonadError[F], verbose: Boolean * of a pre-buffered String. */ private def dispatchInputStreamResponse[T]( - delegate: GenericResponseAs[T, _], + delegate: GenericResponseAs[T, ?], is: InputStream, meta: ResponseMetadata ): F[T] = @@ -535,7 +535,7 @@ abstract class AbstractCurlBackend[F[_]](_monad: MonadError[F], verbose: Boolean } } - private def basicBodyToString(body: BodyPart[_]): String = + private def basicBodyToString(body: BodyPart[?]): String = body match { case StringBody(b, _, _) => b case ByteArrayBody(b, _) => new String(b) @@ -580,7 +580,7 @@ abstract class AbstractCurlBackend[F[_]](_monad: MonadError[F], verbose: Boolean } } - val headers = Seq(lines.tail: _*).map { line => + val headers = Seq(lines.tail*).map { line => val split = line.split(":", 2) if (split.size == 2) Header(split(0).trim, split(1).trim) @@ -613,7 +613,7 @@ abstract class AbstractCurlBackend[F[_]](_monad: MonadError[F], verbose: Boolean throw new IllegalStateException("CurlBackend does not support streaming responses") override protected def handleWS[T]( - responseAs: GenericWebSocketResponseAs[T, _], + responseAs: GenericWebSocketResponseAs[T, ?], meta: ResponseMetadata, ws: Nothing ): F[T] = ws diff --git a/core/src/main/scalanative/sttp/client4/curl/internal/CCurl.scala b/core/src/main/scalanative/sttp/client4/curl/internal/CCurl.scala index 6a28a8b0e4..eeca0fb20b 100644 --- a/core/src/main/scalanative/sttp/client4/curl/internal/CCurl.scala +++ b/core/src/main/scalanative/sttp/client4/curl/internal/CCurl.scala @@ -34,10 +34,10 @@ private[curl] trait CCurl { def setoptLong(handle: Ptr[Curl], option: CInt, parameter: Long): CInt = extern @name("sttp_curl_setopt_pointer") - def setoptPtr(handle: Ptr[Curl], option: CInt, parameter: Ptr[_]): CInt = extern + def setoptPtr(handle: Ptr[Curl], option: CInt, parameter: Ptr[?]): CInt = extern @name("sttp_curl_getinfo_pointer") - def getInfo(handle: Ptr[Curl], info: CInt, parameter: Ptr[_]): CInt = extern + def getInfo(handle: Ptr[Curl], info: CInt, parameter: Ptr[?]): CInt = extern @name("sttp_curl_get_version") def getVersion(): CString = extern diff --git a/core/src/main/scalanative/sttp/client4/curl/internal/CurlApi.scala b/core/src/main/scalanative/sttp/client4/curl/internal/CurlApi.scala index 36cd6fc5d2..170753f6bc 100644 --- a/core/src/main/scalanative/sttp/client4/curl/internal/CurlApi.scala +++ b/core/src/main/scalanative/sttp/client4/curl/internal/CurlApi.scala @@ -44,7 +44,7 @@ private[client4] object CurlApi { def option(option: CurlOption, parameter: Boolean): CurlCode = this.option(option, if (parameter) 1 else 0) - def option(option: CurlOption, parameter: Ptr[_]): CurlCode = + def option(option: CurlOption, parameter: Ptr[?]): CurlCode = CurlCode(CCurl.setoptPtr(handle, option.id, parameter)) def option(option: CurlOption, parameter: CFuncPtr): CurlCode = @@ -59,11 +59,11 @@ private[client4] object CurlApi { def info(curlInfo: CurlInfo, parameter: String)(implicit z: Zone): CurlCode = getInfo(handle, curlInfo, toCString(parameter, StandardCharsets.UTF_8)) - def info(curlInfo: CurlInfo, parameter: Ptr[_]): CurlCode = + def info(curlInfo: CurlInfo, parameter: Ptr[?]): CurlCode = getInfo(handle, curlInfo, parameter) } - private def getInfo(handle: CurlHandle, curlInfo: CurlInfo, parameter: Ptr[_]): CurlCode = + private def getInfo(handle: CurlHandle, curlInfo: CurlInfo, parameter: Ptr[?]): CurlCode = CurlCode(CCurl.getInfo(handle, curlInfo.id, parameter)) implicit class MimeHandleOps(handle: MimeHandle) { @@ -114,7 +114,7 @@ private[client4] object CurlApi { implicit class SlistHandleOps(handle: SlistHandle) { def append(string: String)(implicit z: Zone): Ptr[CurlSlist] = - CCurl.slistAppend(handle, toCString(string)(z)) + CCurl.slistAppend(handle, toCString(string)) def free(): Unit = CCurl.slistFree(handle) diff --git a/core/src/main/scalanative/sttp/client4/curl/internal/package.scala b/core/src/main/scalanative/sttp/client4/curl/internal/package.scala index 67d9b5fd81..169d3d5e24 100644 --- a/core/src/main/scalanative/sttp/client4/curl/internal/package.scala +++ b/core/src/main/scalanative/sttp/client4/curl/internal/package.scala @@ -3,7 +3,7 @@ package sttp.client4.curl import scala.scalanative.unsafe.{CSize, CString, CStruct2, Ptr} package object internal { - type CurlSlist = CStruct2[CString, Ptr[_]] + type CurlSlist = CStruct2[CString, Ptr[?]] type CurlFetch = CStruct2[CString, CSize] val CurlZeroTerminated = -1L diff --git a/core/src/test/scala/sttp/client4/FollowRedirectsBackendTest.scala b/core/src/test/scala/sttp/client4/FollowRedirectsBackendTest.scala index 5c69339d84..586a1b692a 100644 --- a/core/src/test/scala/sttp/client4/FollowRedirectsBackendTest.scala +++ b/core/src/test/scala/sttp/client4/FollowRedirectsBackendTest.scala @@ -53,7 +53,7 @@ class FollowRedirectsBackendTest extends AnyFunSuite with Matchers with EitherVa result.body.value shouldBe "All good!" } - private def cookiesIn(r: GenericRequest[_, _]): Set[String] = + private def cookiesIn(r: GenericRequest[?, ?]): Set[String] = r.header(HeaderNames.Cookie).map(_.split("; ").toSet).getOrElse(Set.empty) // a redirect chain example.com/0 -> /1 -> ... -> /n, where each hop sets a cookie `c`; records the cookies diff --git a/core/src/test/scala/sttp/client4/testing/BackendStubTests.scala b/core/src/test/scala/sttp/client4/testing/BackendStubTests.scala index 1a96ab5690..8c8d99e70b 100644 --- a/core/src/test/scala/sttp/client4/testing/BackendStubTests.scala +++ b/core/src/test/scala/sttp/client4/testing/BackendStubTests.scala @@ -304,8 +304,9 @@ class BackendStubTests extends AnyFlatSpec with Matchers with ScalaFutures { } it should "return a web socket, given a web socket, for a safe websocket-always request" in { + implicit val monad: MonadError[Identity] = IdentityMonad val backend: WebSocketSyncBackend = WebSocketBackendStub.synchronous.whenAnyRequest - .thenRespondAdjust(WebSocketStub.initialReceive(List(WebSocketFrame.text("hello"))).build(IdentityMonad)) + .thenRespondAdjust(WebSocketStub.initialReceive(List(WebSocketFrame.text("hello"))).build[Identity]) val frame = basicRequest .get(uri"ws://example.org") @@ -317,9 +318,10 @@ class BackendStubTests extends AnyFlatSpec with Matchers with ScalaFutures { } it should "return a web socket, given a web socket, for a safe websocket request" in { + implicit val monad: MonadError[Identity] = IdentityMonad val backend: WebSocketSyncBackend = WebSocketBackendStub.synchronous.whenAnyRequest .thenRespondAdjust( - WebSocketStub.initialReceive(List(WebSocketFrame.text("hello"))).build(IdentityMonad), + WebSocketStub.initialReceive(List(WebSocketFrame.text("hello"))).build[Identity], if (TestPlatform.Current == TestPlatform.JS) StatusCode.Ok else StatusCode.SwitchingProtocols ) @@ -333,9 +335,10 @@ class BackendStubTests extends AnyFlatSpec with Matchers with ScalaFutures { } it should "return a web socket, given a web socket, for a safe websocket request using the Try monad" in { + implicit val monad: MonadError[Try] = TryMonad val backend: WebSocketBackend[Try] = WebSocketBackendStub(TryMonad).whenAnyRequest .thenRespondAdjust( - WebSocketStub.initialReceive(List(WebSocketFrame.text("hello"))).build(TryMonad), + WebSocketStub.initialReceive(List(WebSocketFrame.text("hello"))).build[Try], if (TestPlatform.Current == TestPlatform.JS) StatusCode.Ok else StatusCode.SwitchingProtocols ) @@ -493,7 +496,7 @@ class BackendStubTests extends AnyFlatSpec with Matchers with ScalaFutures { } private val s = "Hello, world!" - private val adjustTestData = List[(Any, ResponseAs[_], Any)]( + private val adjustTestData = List[(Any, ResponseAs[?], Any)]( (s, sttp.client4.ignore, Some(())), (s, asString(Utf8), Some(Right(s))), (s.getBytes(Utf8), asString(Utf8), Some(Right(s))), diff --git a/core/src/test/scala/sttp/client4/testing/HttpTest.scala b/core/src/test/scala/sttp/client4/testing/HttpTest.scala index 02634da822..a4a4cf1d29 100644 --- a/core/src/test/scala/sttp/client4/testing/HttpTest.scala +++ b/core/src/test/scala/sttp/client4/testing/HttpTest.scala @@ -139,7 +139,7 @@ trait HttpTest[F[_]] val params = List("a" -> "b", "c" -> "d", "e=" -> "&f") basicRequest .post(uri"$endpoint/echo/form_params/as_params") - .body(params: _*) + .body(params*) .response(asParams) .send(backend) .toFuture() diff --git a/core/src/test/scala/sttp/client4/testing/websocket/WebSocketBufferOverflowTest.scala b/core/src/test/scala/sttp/client4/testing/websocket/WebSocketBufferOverflowTest.scala index 71a2f50142..f9609b16a6 100644 --- a/core/src/test/scala/sttp/client4/testing/websocket/WebSocketBufferOverflowTest.scala +++ b/core/src/test/scala/sttp/client4/testing/websocket/WebSocketBufferOverflowTest.scala @@ -15,7 +15,7 @@ import scala.concurrent.duration.FiniteDuration import sttp.monad.syntax._ import sttp.ws.WebSocket -trait WebSocketBufferOverflowTest[F[_]] { outer: Suite with AsyncFlatSpecLike with WebSocketTest[F] => +trait WebSocketBufferOverflowTest[F[_]] { outer: Suite & AsyncFlatSpecLike & WebSocketTest[F] => implicit def monad: MonadError[F] implicit val convertToFuture: ConvertToFuture[F] def bufferCapacity: Int diff --git a/core/src/test/scala/sttp/client4/testing/websocket/WebSocketConcurrentTest.scala b/core/src/test/scala/sttp/client4/testing/websocket/WebSocketConcurrentTest.scala index 0c74b5e1d6..8a43a5502e 100644 --- a/core/src/test/scala/sttp/client4/testing/websocket/WebSocketConcurrentTest.scala +++ b/core/src/test/scala/sttp/client4/testing/websocket/WebSocketConcurrentTest.scala @@ -10,7 +10,7 @@ import sttp.monad.MonadError import sttp.monad.syntax._ import sttp.ws.WebSocket -trait WebSocketConcurrentTest[F[_]] { outer: Suite with AsyncFlatSpecLike with WebSocketTest[F] => +trait WebSocketConcurrentTest[F[_]] { outer: Suite & AsyncFlatSpecLike & WebSocketTest[F] => implicit def monad: MonadError[F] implicit val convertToFuture: ConvertToFuture[F] diff --git a/core/src/test/scala/sttp/client4/testing/websocket/WebSocketStreamingTest.scala b/core/src/test/scala/sttp/client4/testing/websocket/WebSocketStreamingTest.scala index e7710954ac..76ef87cba4 100644 --- a/core/src/test/scala/sttp/client4/testing/websocket/WebSocketStreamingTest.scala +++ b/core/src/test/scala/sttp/client4/testing/websocket/WebSocketStreamingTest.scala @@ -16,7 +16,7 @@ import java.util.concurrent.ConcurrentLinkedQueue import java.util.concurrent.atomic.AtomicReference import scala.collection.JavaConverters._ -trait WebSocketStreamingTest[F[_], S] extends ToFutureWrapper { outer: Suite with AsyncFlatSpecLike with Matchers => +trait WebSocketStreamingTest[F[_], S] extends ToFutureWrapper { outer: Suite & AsyncFlatSpecLike & Matchers => val streams: Streams[S] val backend: WebSocketStreamBackend[F, S] implicit def monad: MonadError[F] @@ -24,7 +24,7 @@ trait WebSocketStreamingTest[F[_], S] extends ToFutureWrapper { outer: Suite wit def webSocketPipeTerminatedByServerTest( postfix: String - )(pipe: ConcurrentLinkedQueue[String] => streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame]) = + )(pipe: ConcurrentLinkedQueue[String] => streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame]) = it should s"use pipe to process websocket messages - server-terminated - $postfix" in { val received = new ConcurrentLinkedQueue[String]() basicRequest @@ -39,7 +39,7 @@ trait WebSocketStreamingTest[F[_], S] extends ToFutureWrapper { outer: Suite wit def webSocketPipeClientTerminated( postfix: String - )(pipe: ConcurrentLinkedQueue[String] => streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame]) = + )(pipe: ConcurrentLinkedQueue[String] => streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame]) = it should s"use pipe to process websocket messages - client-terminated - $postfix" in { val received = new ConcurrentLinkedQueue[String]() basicRequest @@ -106,12 +106,12 @@ trait WebSocketStreamingTest[F[_], S] extends ToFutureWrapper { outer: Suite wit } def prepend(item: WebSocketFrame.Text)( - to: streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] - ): streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] + to: streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] + ): streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] - def fromTextPipe(function: String => WebSocketFrame): streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] + def fromTextPipe(function: String => WebSocketFrame): streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] def functionToPipe( - f: WebSocketFrame.Data[_] => Option[WebSocketFrame] - ): streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] + f: WebSocketFrame.Data[?] => Option[WebSocketFrame] + ): streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] } diff --git a/core/src/test/scalajvm/sttp/client4/ToCurlConverterTestExtension.scala b/core/src/test/scalajvm/sttp/client4/ToCurlConverterTestExtension.scala index ea79adfb27..82a1e7dc56 100644 --- a/core/src/test/scalajvm/sttp/client4/ToCurlConverterTestExtension.scala +++ b/core/src/test/scalajvm/sttp/client4/ToCurlConverterTestExtension.scala @@ -7,7 +7,7 @@ import sttp.client4.internal.SttpFile import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers -trait ToCurlConverterTestExtension { suit: Suite with AnyFlatSpec with Matchers => +trait ToCurlConverterTestExtension { suit: Suite & AnyFlatSpec & Matchers => it should "render multipart form data if content is a file" in { basicRequest .multipartBody(multipartSttpFile("upload", SttpFile.fromPath(new File("myDataSet").toPath))) diff --git a/core/src/test/scalanative/sttp/client4/testing/SyncHttpTest.scala b/core/src/test/scalanative/sttp/client4/testing/SyncHttpTest.scala index 7742345639..072da88c44 100644 --- a/core/src/test/scalanative/sttp/client4/testing/SyncHttpTest.scala +++ b/core/src/test/scalanative/sttp/client4/testing/SyncHttpTest.scala @@ -79,7 +79,7 @@ trait SyncHttpTest val params = List("a" -> "b", "c" -> "d", "e=" -> "&f") val response = basicRequest .post(uri"$endpoint/echo/form_params/as_params") - .body(params: _*) + .body(params*) .response(asParams) .send(backend) response.body.right.map(_.toList) should be(Right(params)) diff --git a/docs/conf/redirects.md b/docs/conf/redirects.md index fc6fa74ebf..c12566869f 100644 --- a/docs/conf/redirects.md +++ b/docs/conf/redirects.md @@ -78,7 +78,7 @@ import sttp.monad.MonadError abstract class MyWrapper[F[_], P] private (delegate: GenericBackend[F, P]) extends GenericBackend[F, P]: - def send[T](request: GenericRequest[T, P with Effect[F]]): F[Response[T]] = ??? + def send[T](request: GenericRequest[T, P & Effect[F]]): F[Response[T]] = ??? def close(): F[Unit] = ??? diff --git a/docs/index.md b/docs/index.md index 04beda410e..82657a2c8b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -4,7 +4,7 @@ Welcome! sttp client is an open-source HTTP client for Scala, supporting various approaches to writing Scala code: synchronous (direct-style), `Future`-based, and using functional effect systems (cats-effect, ZIO, Monix, Kyo, scalaz). -The library is available for Scala 2.12, 2.13 and 3. Supported platforms are the JVM (Java 11+), Scala.JS and Scala Native. +The library is available for Scala 2.12, 2.13 and 3. Supported platforms are the JVM (Java 11+ for Scala 2, Java 17+ for Scala 3), Scala.JS and Scala Native. Here's a quick example of sttp client in action, runnable using [scala-cli](https://scala-cli.virtuslab.org): diff --git a/docs/other/websockets.md b/docs/other/websockets.md index f015196dea..fdf04bb758 100644 --- a/docs/other/websockets.md +++ b/docs/other/websockets.md @@ -71,10 +71,10 @@ import sttp.ws.WebSocketFrame // when using import sttp.client4.ws.stream._ -def asWebSocketStream[S](s: Streams[S])(p: s.Pipe[WebSocketFrame.Data[_], WebSocketFrame]): +def asWebSocketStream[S](s: Streams[S])(p: s.Pipe[WebSocketFrame.Data[?], WebSocketFrame]): WebSocketStreamResponseAs[Either[String, Unit], S] = ??? -def asWebSocketStreamOrFail[S](s: Streams[S])(p: s.Pipe[WebSocketFrame.Data[_], WebSocketFrame]): +def asWebSocketStreamOrFail[S](s: Streams[S])(p: s.Pipe[WebSocketFrame.Data[?], WebSocketFrame]): WebSocketStreamResponseAs[Unit, S] = ??? ``` diff --git a/docs/quickstart.md b/docs/quickstart.md index 1907d6e954..5adb6c1b34 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -5,7 +5,7 @@ This also includes [synchronous](backends/synchronous.md) and [`Future`-based](b To integrate with other parts of your application and various effect systems, you'll often need to use an alternate backend, or backend wrappers (but what's important is that the API remains the same!). See the section on [backends](backends/summary.md) for a short guide on which backend to choose, and a list of all implementations. -sttp client is available for Scala 2.12, 2.13 and 3, on the JVM (Java 11+), Scala.JS and Scala Native platforms. Note that not all modules are compatible with these platforms, and that each has its own dedicated set of backends. +sttp client is available for Scala 2.12, 2.13 and 3, on the JVM (Java 11+ for Scala 2, Java 17+ for Scala 3), Scala.JS and Scala Native platforms. Note that not all modules are compatible with these platforms, and that each has its own dedicated set of backends. ## Using sbt diff --git a/docs/responses/body.md b/docs/responses/body.md index 8f6e76e94e..7744ca8d07 100644 --- a/docs/responses/body.md +++ b/docs/responses/body.md @@ -201,21 +201,21 @@ import sttp.client4.* import sttp.model.ResponseMetadata def asStream[F[_], T, S](s: Streams[S])(f: s.BinaryStream => F[T]): - StreamResponseAs[Either[String, T], Effect[F] with S] = ??? + StreamResponseAs[Either[String, T], Effect[F] & S] = ??? def asStreamOrFail[F[_], T, S](s: Streams[S])(f: s.BinaryStream => F[T]): - StreamResponseAs[T, S with Effect[F]] = ??? + StreamResponseAs[T, S & Effect[F]] = ??? def asStreamWithMetadata[F[_], T, S](s: Streams[S])( f: (s.BinaryStream, ResponseMetadata) => F[T] - ): StreamResponseAs[Either[String, T], Effect[F] with S] = ??? + ): StreamResponseAs[Either[String, T], Effect[F] & S] = ??? def asStreamAlways[F[_], T, S](s: Streams[S])(f: s.BinaryStream => F[T]): - StreamResponseAs[T, Effect[F] with S] = ??? + StreamResponseAs[T, Effect[F] & S] = ??? def asStreamAlwaysWithMetadata[F[_], T, S](s: Streams[S])( f: (s.BinaryStream, ResponseMetadata) => F[T] - ): StreamResponseAs[T, Effect[F] with S] = ??? + ): StreamResponseAs[T, Effect[F] & S] = ??? def asStreamUnsafe[S](s: Streams[S]): StreamResponseAs[Either[String, s.BinaryStream], S] = ??? diff --git a/docs/testing/stub.md b/docs/testing/stub.md index 7a5bf9ab39..831647edb7 100644 --- a/docs/testing/stub.md +++ b/docs/testing/stub.md @@ -344,6 +344,6 @@ val testingBackend = RecordingBackend( val response1 = basicRequest.get(uri"http://example.org/a/b/c").send(testingBackend) // response1.body will be Right("Hello there") -testingBackend.allInteractions: List[(GenericRequest[_, _], Try[Response[_]])] +testingBackend.allInteractions: List[(GenericRequest[?, ?], Try[Response[?]])] // the list will contain one element and can be verified in a test ``` diff --git a/effects/cats/src/main/scalajvm/sttp/client4/httpclient/cats/HttpClientCatsBackend.scala b/effects/cats/src/main/scalajvm/sttp/client4/httpclient/cats/HttpClientCatsBackend.scala index f6453f026a..807d3b3e8a 100644 --- a/effects/cats/src/main/scalajvm/sttp/client4/httpclient/cats/HttpClientCatsBackend.scala +++ b/effects/cats/src/main/scalajvm/sttp/client4/httpclient/cats/HttpClientCatsBackend.scala @@ -72,7 +72,7 @@ class HttpClientCatsBackend[F[_]: Async] private ( override implicit def monad: MonadError[F] = self.monad override def compileWebSocketPipe( ws: WebSocket[F], - pipe: streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] + pipe: streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] ): F[Unit] = pipe } diff --git a/effects/cats/src/test/scalajvm/sttp/client4/impl/cats/CatsListenerBackendTest.scala b/effects/cats/src/test/scalajvm/sttp/client4/impl/cats/CatsListenerBackendTest.scala index 38e36e85fb..ece3269aba 100644 --- a/effects/cats/src/test/scalajvm/sttp/client4/impl/cats/CatsListenerBackendTest.scala +++ b/effects/cats/src/test/scalajvm/sttp/client4/impl/cats/CatsListenerBackendTest.scala @@ -62,16 +62,16 @@ class CatsListenerBackendTest extends AnyFlatSpec with Matchers { }.unsafeRunSync() def spyingListener(trail: Ref[IO, List[String]]) = new RequestListener[IO, Unit] { - override def before(request: GenericRequest[_, _]): IO[Unit] = trail.update(_ :+ "before") - override def responseBodyReceived(request: GenericRequest[_, _], response: ResponseMetadata, tag: Unit): Unit = () + override def before(request: GenericRequest[?, ?]): IO[Unit] = trail.update(_ :+ "before") + override def responseBodyReceived(request: GenericRequest[?, ?], response: ResponseMetadata, tag: Unit): Unit = () override def responseHandled( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], response: ResponseMetadata, tag: Unit, - exception: Option[ResponseException[_]] + exception: Option[ResponseException[?]] ): IO[Unit] = trail.update(_ :+ "response handled") override def exception( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], tag: Unit, exception: Throwable, responseBodyReceivedCalled: Boolean diff --git a/effects/cats/src/test/scalajvm/sttp/client4/impl/cats/TestIODispatcher.scala b/effects/cats/src/test/scalajvm/sttp/client4/impl/cats/TestIODispatcher.scala index 67786cfa7a..fb44b18985 100644 --- a/effects/cats/src/test/scalajvm/sttp/client4/impl/cats/TestIODispatcher.scala +++ b/effects/cats/src/test/scalajvm/sttp/client4/impl/cats/TestIODispatcher.scala @@ -8,7 +8,7 @@ import org.scalatest.{BeforeAndAfterAll, Suite} trait TestIODispatcher extends BeforeAndAfterAll { this: Suite => // use a var to avoid initialization error `scala.UninitializedFieldError` - protected var dispatcher: Dispatcher[IO] = _ + protected var dispatcher: Dispatcher[IO] = null private val (d, shutdownDispatcher) = Dispatcher.parallel[IO].allocated.unsafeRunSync() dispatcher = d diff --git a/effects/fs2-ce2/src/main/scala/sttp/client4/impl/fs2/Fs2WebSockets.scala b/effects/fs2-ce2/src/main/scala/sttp/client4/impl/fs2/Fs2WebSockets.scala index 8f0ebc875b..00d2d8930e 100644 --- a/effects/fs2-ce2/src/main/scala/sttp/client4/impl/fs2/Fs2WebSockets.scala +++ b/effects/fs2-ce2/src/main/scala/sttp/client4/impl/fs2/Fs2WebSockets.scala @@ -24,14 +24,14 @@ object Fs2WebSockets { */ def handleThroughPipe[F[_]: ConcurrentEffect]( ws: WebSocket[F] - )(pipe: Pipe[F, WebSocketFrame.Data[_], WebSocketFrame]): F[Unit] = + )(pipe: Pipe[F, WebSocketFrame.Data[?], WebSocketFrame]): F[Unit] = Ref.of[F, Boolean](false).flatMap { closeSent => Stream .eval(Ref.of[F, Option[WebSocketFrame.Close]](None)) .flatMap { closeRef => Stream .repeatEval(ws.receive()) // read incoming messages - .flatMap[F, Option[WebSocketFrame.Data[_]]] { + .flatMap[F, Option[WebSocketFrame.Data[?]]] { case WebSocketFrame.Close(code, reason) => Stream.eval(closeRef.set(Some(WebSocketFrame.Close(code, reason)))).as(None) case WebSocketFrame.Ping(payload) => diff --git a/effects/fs2-ce2/src/main/scalajvm/sttp/client4/httpclient/fs2/Fs2BodyFromHttpClient.scala b/effects/fs2-ce2/src/main/scalajvm/sttp/client4/httpclient/fs2/Fs2BodyFromHttpClient.scala index 18e8e96de4..b95405e789 100644 --- a/effects/fs2-ce2/src/main/scalajvm/sttp/client4/httpclient/fs2/Fs2BodyFromHttpClient.scala +++ b/effects/fs2-ce2/src/main/scalajvm/sttp/client4/httpclient/fs2/Fs2BodyFromHttpClient.scala @@ -20,7 +20,7 @@ private[fs2] class Fs2BodyFromHttpClient[F[_]: ConcurrentEffect: ContextShift](b override implicit val monad: MonadError[F] = new CatsMonadAsyncError[F] override def compileWebSocketPipe( ws: WebSocket[F], - pipe: Pipe[F, WebSocketFrame.Data[_], WebSocketFrame] + pipe: Pipe[F, WebSocketFrame.Data[?], WebSocketFrame] ): F[Unit] = Fs2WebSockets.handleThroughPipe(ws)(pipe) override protected def bodyFromResponseAs: BodyFromResponseAs[F, Stream[F, Byte], WebSocket[F], Stream[F, Byte]] = @@ -54,7 +54,7 @@ private[fs2] class Fs2BodyFromHttpClient[F[_]: ConcurrentEffect: ContextShift](b ).unit override protected def handleWS[T]( - responseAs: GenericWebSocketResponseAs[T, _], + responseAs: GenericWebSocketResponseAs[T, ?], meta: ResponseMetadata, ws: WebSocket[F] ): F[T] = bodyFromWs(responseAs, ws, meta) diff --git a/effects/fs2-ce2/src/main/scalajvm/sttp/client4/httpclient/fs2/HttpClientFs2Backend.scala b/effects/fs2-ce2/src/main/scalajvm/sttp/client4/httpclient/fs2/HttpClientFs2Backend.scala index 0fa96c7615..7f7d81424c 100644 --- a/effects/fs2-ce2/src/main/scalajvm/sttp/client4/httpclient/fs2/HttpClientFs2Backend.scala +++ b/effects/fs2-ce2/src/main/scalajvm/sttp/client4/httpclient/fs2/HttpClientFs2Backend.scala @@ -150,6 +150,11 @@ object HttpClientFs2Backend { List(new GZipFs2Decompressor, new DeflateFs2Decompressor) ) + private def defaultCompressionHandlersFor[F[_]](F: Sync[F]): CompressionHandlers[Fs2Streams[F], Stream[F, Byte]] = { + implicit val ev: Sync[F] = F + defaultCompressionHandlers[F] + } + private def apply[F[_]: ConcurrentEffect: ContextShift]( client: HttpClient, blocker: Blocker, @@ -166,7 +171,7 @@ object HttpClientFs2Backend { options: BackendOptions = BackendOptions.Default, customizeRequest: HttpRequest => HttpRequest = identity, compressionHandlers: Sync[F] => CompressionHandlers[Fs2Streams[F], Stream[F, Byte]] = - defaultCompressionHandlers[F](_: Sync[F]) + defaultCompressionHandlersFor[F](_) ): F[WebSocketStreamBackend[F, Fs2Streams[F]]] = Sync[F].delay( HttpClientFs2Backend( @@ -183,7 +188,7 @@ object HttpClientFs2Backend { options: BackendOptions = BackendOptions.Default, customizeRequest: HttpRequest => HttpRequest = identity, compressionHandlers: Sync[F] => CompressionHandlers[Fs2Streams[F], Stream[F, Byte]] = - defaultCompressionHandlers[F](_: Sync[F]) + defaultCompressionHandlersFor[F](_) ): Resource[F, WebSocketStreamBackend[F, Fs2Streams[F]]] = Resource.make(apply(blocker, options, customizeRequest, compressionHandlers))(_.close()) @@ -193,7 +198,7 @@ object HttpClientFs2Backend { blocker: Blocker, customizeRequest: HttpRequest => HttpRequest = identity, compressionHandlers: Sync[F] => CompressionHandlers[Fs2Streams[F], Stream[F, Byte]] = - defaultCompressionHandlers[F](_: Sync[F]) + defaultCompressionHandlersFor[F](_) ): Resource[F, WebSocketStreamBackend[F, Fs2Streams[F]]] = Resource.make( Sync[F].delay( @@ -206,7 +211,7 @@ object HttpClientFs2Backend { blocker: Blocker, customizeRequest: HttpRequest => HttpRequest = identity, compressionHandlers: Sync[F] => CompressionHandlers[Fs2Streams[F], Stream[F, Byte]] = - defaultCompressionHandlers[F](_: Sync[F]) + defaultCompressionHandlersFor[F](_) ): WebSocketStreamBackend[F, Fs2Streams[F]] = HttpClientFs2Backend(client, blocker, closeClient = false, customizeRequest, compressionHandlers(implicitly)) diff --git a/effects/fs2-ce2/src/test/scalajvm/sttp/client4/httpclient/fs2/HttpClientFs2WebSocketTest.scala b/effects/fs2-ce2/src/test/scalajvm/sttp/client4/httpclient/fs2/HttpClientFs2WebSocketTest.scala index ce617c8b6b..7601d15d94 100644 --- a/effects/fs2-ce2/src/test/scalajvm/sttp/client4/httpclient/fs2/HttpClientFs2WebSocketTest.scala +++ b/effects/fs2-ce2/src/test/scalajvm/sttp/client4/httpclient/fs2/HttpClientFs2WebSocketTest.scala @@ -16,17 +16,17 @@ class HttpClientFs2WebSocketTest override val streams: Fs2Streams[IO] = new Fs2Streams[IO] {} override def functionToPipe( - f: WebSocketFrame.Data[_] => Option[WebSocketFrame] - ): fs2.Pipe[IO, WebSocketFrame.Data[_], WebSocketFrame] = in => in.mapFilter(f) + f: WebSocketFrame.Data[?] => Option[WebSocketFrame] + ): fs2.Pipe[IO, WebSocketFrame.Data[?], WebSocketFrame] = in => in.mapFilter(f) override def fromTextPipe( function: String => WebSocketFrame - ): Pipe[IO, WebSocketFrame.Data[_], WebSocketFrame] = + ): Pipe[IO, WebSocketFrame.Data[?], WebSocketFrame] = Fs2WebSockets.fromTextPipe[IO](function) override def prepend( item: WebSocketFrame.Text - )(to: Pipe[IO, WebSocketFrame.Data[_], WebSocketFrame]): Pipe[IO, WebSocketFrame.Data[_], WebSocketFrame] = + )(to: Pipe[IO, WebSocketFrame.Data[?], WebSocketFrame]): Pipe[IO, WebSocketFrame.Data[?], WebSocketFrame] = to.andThen(rest => fs2.Stream.eval(item.pure[IO]) ++ rest) override def concurrently[T](fs: List[() => IO[T]]): IO[List[T]] = fs.map(_()).parSequence diff --git a/effects/fs2-ce2/src/test/scalajvm/sttp/client4/impl/fs2/Fs2WebSocketsTest.scala b/effects/fs2-ce2/src/test/scalajvm/sttp/client4/impl/fs2/Fs2WebSocketsTest.scala index 0c7908ffca..54fca70725 100644 --- a/effects/fs2-ce2/src/test/scalajvm/sttp/client4/impl/fs2/Fs2WebSocketsTest.scala +++ b/effects/fs2-ce2/src/test/scalajvm/sttp/client4/impl/fs2/Fs2WebSocketsTest.scala @@ -44,7 +44,7 @@ class Fs2WebSocketsTest extends AnyFlatSpec with Matchers { } private def sentFrames(incoming: List[WebSocketFrame])( - pipe: Pipe[IO, WebSocketFrame.Data[_], WebSocketFrame] + pipe: Pipe[IO, WebSocketFrame.Data[?], WebSocketFrame] ): List[(WebSocketFrame, Boolean)] = (for { incomingRef <- Ref.of[IO, List[WebSocketFrame]](incoming) diff --git a/effects/fs2/src/main/scala/sttp/client4/impl/fs2/Fs2WebSockets.scala b/effects/fs2/src/main/scala/sttp/client4/impl/fs2/Fs2WebSockets.scala index 40451eda2b..73fc3d5e9f 100644 --- a/effects/fs2/src/main/scala/sttp/client4/impl/fs2/Fs2WebSockets.scala +++ b/effects/fs2/src/main/scala/sttp/client4/impl/fs2/Fs2WebSockets.scala @@ -23,14 +23,14 @@ object Fs2WebSockets { */ def handleThroughPipe[F[_]: Concurrent]( ws: WebSocket[F] - )(pipe: Pipe[F, WebSocketFrame.Data[_], WebSocketFrame]): F[Unit] = + )(pipe: Pipe[F, WebSocketFrame.Data[?], WebSocketFrame]): F[Unit] = Ref.of[F, Boolean](false).flatMap { closeSent => Stream .eval(Ref.of[F, Option[WebSocketFrame.Close]](None)) .flatMap { closeRef => Stream .repeatEval(ws.receive()) // read incoming messages - .flatMap[F, Option[WebSocketFrame.Data[_]]] { + .flatMap[F, Option[WebSocketFrame.Data[?]]] { case WebSocketFrame.Close(code, reason) => Stream.eval(closeRef.set(Some(WebSocketFrame.Close(code, reason)))).as(None) case WebSocketFrame.Ping(payload) => diff --git a/effects/fs2/src/main/scalajs/sttp.client4.impl.fs2/FetchFs2Backend.scala b/effects/fs2/src/main/scalajs/sttp.client4.impl.fs2/FetchFs2Backend.scala index e07be621ea..80271ade16 100644 --- a/effects/fs2/src/main/scalajs/sttp.client4.impl.fs2/FetchFs2Backend.scala +++ b/effects/fs2/src/main/scalajs/sttp.client4.impl.fs2/FetchFs2Backend.scala @@ -39,7 +39,7 @@ class FetchFs2Backend[F[_]: Async] private (fetchOptions: FetchOptions, customiz override protected def compileWebSocketPipe( ws: WebSocket[F], - pipe: streams.Pipe[Data[_], WebSocketFrame] + pipe: streams.Pipe[Data[?], WebSocketFrame] ): F[Unit] = { Fs2WebSockets.handleThroughPipe[F](ws)(pipe) } diff --git a/effects/fs2/src/main/scalajvm/sttp/client4/httpclient/fs2/Fs2BodyFromHttpClient.scala b/effects/fs2/src/main/scalajvm/sttp/client4/httpclient/fs2/Fs2BodyFromHttpClient.scala index 1e70578071..89a76ae8b1 100644 --- a/effects/fs2/src/main/scalajvm/sttp/client4/httpclient/fs2/Fs2BodyFromHttpClient.scala +++ b/effects/fs2/src/main/scalajvm/sttp/client4/httpclient/fs2/Fs2BodyFromHttpClient.scala @@ -20,7 +20,7 @@ private[fs2] class Fs2BodyFromHttpClient[F[_]: Async]() extends BodyFromHttpClie override implicit val monad: MonadError[F] = new CatsMonadAsyncError[F] override def compileWebSocketPipe( ws: WebSocket[F], - pipe: Pipe[F, WebSocketFrame.Data[_], WebSocketFrame] + pipe: Pipe[F, WebSocketFrame.Data[?], WebSocketFrame] ): F[Unit] = Fs2WebSockets.handleThroughPipe(ws)(pipe) override protected def bodyFromResponseAs: BodyFromResponseAs[F, Stream[F, Byte], WebSocket[F], Stream[F, Byte]] = @@ -54,7 +54,7 @@ private[fs2] class Fs2BodyFromHttpClient[F[_]: Async]() extends BodyFromHttpClie ).unit override protected def handleWS[T]( - responseAs: GenericWebSocketResponseAs[T, _], + responseAs: GenericWebSocketResponseAs[T, ?], meta: ResponseMetadata, ws: WebSocket[F] ): F[T] = bodyFromWs(responseAs, ws, meta) diff --git a/effects/fs2/src/main/scalajvm/sttp/client4/httpclient/fs2/HttpClientFs2Backend.scala b/effects/fs2/src/main/scalajvm/sttp/client4/httpclient/fs2/HttpClientFs2Backend.scala index 66117c1dd2..8b403cba21 100644 --- a/effects/fs2/src/main/scalajvm/sttp/client4/httpclient/fs2/HttpClientFs2Backend.scala +++ b/effects/fs2/src/main/scalajvm/sttp/client4/httpclient/fs2/HttpClientFs2Backend.scala @@ -140,6 +140,11 @@ object HttpClientFs2Backend { List(new GZipFs2Decompressor, new DeflateFs2Decompressor) ) + private def defaultCompressionHandlersFor[F[_]](F: Async[F]): CompressionHandlers[Fs2Streams[F], Stream[F, Byte]] = { + implicit val ev: Async[F] = F + defaultCompressionHandlers[F] + } + private def apply[F[_]: Async]( client: HttpClient, closeClient: Boolean, @@ -156,7 +161,7 @@ object HttpClientFs2Backend { options: BackendOptions = BackendOptions.Default, customizeRequest: HttpRequest => HttpRequest = identity, compressionHandlers: Async[F] => CompressionHandlers[Fs2Streams[F], Stream[F, Byte]] = - defaultCompressionHandlers[F](_: Async[F]) + defaultCompressionHandlersFor[F](_) ): F[WebSocketStreamBackend[F, Fs2Streams[F]]] = Async[F].executor.flatMap(executor => Sync[F].delay( @@ -174,7 +179,7 @@ object HttpClientFs2Backend { options: BackendOptions = BackendOptions.Default, customizeRequest: HttpRequest => HttpRequest = identity, compressionHandlers: Async[F] => CompressionHandlers[Fs2Streams[F], Stream[F, Byte]] = - defaultCompressionHandlers[F](_: Async[F]) + defaultCompressionHandlersFor[F](_) ): Resource[F, WebSocketStreamBackend[F, Fs2Streams[F]]] = Dispatcher .parallel[F] @@ -187,7 +192,7 @@ object HttpClientFs2Backend { client: HttpClient, customizeRequest: HttpRequest => HttpRequest = identity, compressionHandlers: Async[F] => CompressionHandlers[Fs2Streams[F], Stream[F, Byte]] = - defaultCompressionHandlers[F](_: Async[F]) + defaultCompressionHandlersFor[F](_) ): Resource[F, WebSocketStreamBackend[F, Fs2Streams[F]]] = Dispatcher .parallel[F] @@ -203,7 +208,7 @@ object HttpClientFs2Backend { dispatcher: Dispatcher[F], customizeRequest: HttpRequest => HttpRequest = identity, compressionHandlers: Async[F] => CompressionHandlers[Fs2Streams[F], Stream[F, Byte]] = - defaultCompressionHandlers[F](_: Async[F]) + defaultCompressionHandlersFor[F](_) ): WebSocketStreamBackend[F, Fs2Streams[F]] = HttpClientFs2Backend(client, closeClient = false, customizeRequest, compressionHandlers(implicitly), dispatcher) diff --git a/effects/fs2/src/main/scalajvmnative/sttp/client4/impl/fs2/fs2CompressorPlatform.scala b/effects/fs2/src/main/scalajvmnative/sttp/client4/impl/fs2/fs2CompressorPlatform.scala index d8f2bc9311..b38fec1d25 100644 --- a/effects/fs2/src/main/scalajvmnative/sttp/client4/impl/fs2/fs2CompressorPlatform.scala +++ b/effects/fs2/src/main/scalajvmnative/sttp/client4/impl/fs2/fs2CompressorPlatform.scala @@ -9,7 +9,7 @@ import sttp.client4._ class PlatformGZipFs2Compressor[F[_]: Sync: Files, R <: Fs2Streams[F]] extends GZipFs2Compressor[F, R] { override protected def compressInputStreamBody(b: java.io.InputStream): GenericRequestBody[R] = - StreamBody(Fs2Streams[F])(compressStream(fs2.io.readInputStream(fSync.delay(b), 1024)(fSync))) + StreamBody(Fs2Streams[F])(compressStream(fs2.io.readInputStream(fSync.delay(b), 1024))) override protected def compressFileBody(fb: FileBody): GenericRequestBody[R] = StreamBody(Fs2Streams[F])(compressStream(Files[F].readAll(fb.f.toPath, 1024))) @@ -18,7 +18,7 @@ class PlatformGZipFs2Compressor[F[_]: Sync: Files, R <: Fs2Streams[F]] extends G class PlatformDeflateFs2Compressor[F[_]: Sync: Files, R <: Fs2Streams[F]] extends DeflateFs2Compressor[F, R] { override protected def compressInputStreamBody(b: java.io.InputStream): GenericRequestBody[R] = - StreamBody(Fs2Streams[F])(compressStream(fs2.io.readInputStream(fSync.delay(b), 1024)(fSync))) + StreamBody(Fs2Streams[F])(compressStream(fs2.io.readInputStream(fSync.delay(b), 1024))) override protected def compressFileBody(fb: FileBody): GenericRequestBody[R] = StreamBody(Fs2Streams[F])(compressStream(Files[F].readAll(fb.f.toPath, 1024))) diff --git a/effects/fs2/src/test/scalajs/sttp/client4/impl/fs2/FetchFs2WebSocketTest.scala b/effects/fs2/src/test/scalajs/sttp/client4/impl/fs2/FetchFs2WebSocketTest.scala index 8689b87ab2..b7c278324d 100644 --- a/effects/fs2/src/test/scalajs/sttp/client4/impl/fs2/FetchFs2WebSocketTest.scala +++ b/effects/fs2/src/test/scalajs/sttp/client4/impl/fs2/FetchFs2WebSocketTest.scala @@ -25,16 +25,16 @@ class FetchFs2WebSocketTest override val streams: Fs2Streams[IO] = Fs2Streams[IO] override def prepend(item: WebSocketFrame.Text)( - to: streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] - ): streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] = + to: streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] + ): streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] = to.andThen(rest => Stream(item) ++ rest) - override def fromTextPipe(function: String => WebSocketFrame): streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] = + override def fromTextPipe(function: String => WebSocketFrame): streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] = Fs2WebSockets.fromTextPipe(function) override def functionToPipe( - f: WebSocketFrame.Data[_] => Option[WebSocketFrame] - ): streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] = _.map(f).collect { case Some(v) => + f: WebSocketFrame.Data[?] => Option[WebSocketFrame] + ): streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] = _.map(f).collect { case Some(v) => v } } diff --git a/effects/fs2/src/test/scalajvm/sttp/client4/httpclient/fs2/HttpClientFs2WebSocketTest.scala b/effects/fs2/src/test/scalajvm/sttp/client4/httpclient/fs2/HttpClientFs2WebSocketTest.scala index ce617c8b6b..7601d15d94 100644 --- a/effects/fs2/src/test/scalajvm/sttp/client4/httpclient/fs2/HttpClientFs2WebSocketTest.scala +++ b/effects/fs2/src/test/scalajvm/sttp/client4/httpclient/fs2/HttpClientFs2WebSocketTest.scala @@ -16,17 +16,17 @@ class HttpClientFs2WebSocketTest override val streams: Fs2Streams[IO] = new Fs2Streams[IO] {} override def functionToPipe( - f: WebSocketFrame.Data[_] => Option[WebSocketFrame] - ): fs2.Pipe[IO, WebSocketFrame.Data[_], WebSocketFrame] = in => in.mapFilter(f) + f: WebSocketFrame.Data[?] => Option[WebSocketFrame] + ): fs2.Pipe[IO, WebSocketFrame.Data[?], WebSocketFrame] = in => in.mapFilter(f) override def fromTextPipe( function: String => WebSocketFrame - ): Pipe[IO, WebSocketFrame.Data[_], WebSocketFrame] = + ): Pipe[IO, WebSocketFrame.Data[?], WebSocketFrame] = Fs2WebSockets.fromTextPipe[IO](function) override def prepend( item: WebSocketFrame.Text - )(to: Pipe[IO, WebSocketFrame.Data[_], WebSocketFrame]): Pipe[IO, WebSocketFrame.Data[_], WebSocketFrame] = + )(to: Pipe[IO, WebSocketFrame.Data[?], WebSocketFrame]): Pipe[IO, WebSocketFrame.Data[?], WebSocketFrame] = to.andThen(rest => fs2.Stream.eval(item.pure[IO]) ++ rest) override def concurrently[T](fs: List[() => IO[T]]): IO[List[T]] = fs.map(_()).parSequence diff --git a/effects/fs2/src/test/scalajvm/sttp/client4/impl/fs2/Fs2WebSocketsTest.scala b/effects/fs2/src/test/scalajvm/sttp/client4/impl/fs2/Fs2WebSocketsTest.scala index 181db82569..f8f5f7569f 100644 --- a/effects/fs2/src/test/scalajvm/sttp/client4/impl/fs2/Fs2WebSocketsTest.scala +++ b/effects/fs2/src/test/scalajvm/sttp/client4/impl/fs2/Fs2WebSocketsTest.scala @@ -41,7 +41,7 @@ class Fs2WebSocketsTest extends AnyFlatSpec with Matchers { } private def sentFrames(incoming: List[WebSocketFrame])( - pipe: Pipe[IO, WebSocketFrame.Data[_], WebSocketFrame] + pipe: Pipe[IO, WebSocketFrame.Data[?], WebSocketFrame] ): List[(WebSocketFrame, Boolean)] = (for { incomingRef <- Ref.of[IO, List[WebSocketFrame]](incoming) diff --git a/effects/monix/src/main/scala/sttp/client4/impl/monix/MonixWebSockets.scala b/effects/monix/src/main/scala/sttp/client4/impl/monix/MonixWebSockets.scala index 93ba04db8a..072fd74696 100644 --- a/effects/monix/src/main/scala/sttp/client4/impl/monix/MonixWebSockets.scala +++ b/effects/monix/src/main/scala/sttp/client4/impl/monix/MonixWebSockets.scala @@ -10,21 +10,21 @@ import sttp.ws.{WebSocket, WebSocketClosed, WebSocketFrame} object MonixWebSockets { def compilePipe( ws: WebSocket[Task], - pipe: Observable[WebSocketFrame.Data[_]] => Observable[WebSocketFrame] + pipe: Observable[WebSocketFrame.Data[?]] => Observable[WebSocketFrame] ): Task[Unit] = Task(BooleanCancelable()).flatMap { wsClosed => Ref.of[Task, Option[WebSocketFrame.Close]](None).flatMap { closeRef => Ref.of[Task, Boolean](false).flatMap { closeSent => // set the close to echo (a received Close) or none (the connection is already gone), // then terminate the stream - def onClose(close: Option[WebSocketFrame.Close]): Task[Option[WebSocketFrame.Data[_]]] = + def onClose(close: Option[WebSocketFrame.Close]): Task[Option[WebSocketFrame.Data[?]]] = closeRef.set(close) >> Task { wsClosed.cancel() None } pipe( Observable - .repeatEvalF(ws.receive().flatMap[Option[WebSocketFrame.Data[_]]] { + .repeatEvalF(ws.receive().flatMap[Option[WebSocketFrame.Data[?]]] { case WebSocketFrame.Close(code, reason) => onClose(Some(WebSocketFrame.Close(code, reason))) case WebSocketFrame.Ping(payload) => ws.send(WebSocketFrame.Pong(payload)).map(_ => None) case WebSocketFrame.Pong(_) => Task.now(None) diff --git a/effects/monix/src/main/scalajs/sttp/client4/impl/monix/FetchMonixBackend.scala b/effects/monix/src/main/scalajs/sttp/client4/impl/monix/FetchMonixBackend.scala index 7b59bd2711..6204f87d2f 100644 --- a/effects/monix/src/main/scalajs/sttp/client4/impl/monix/FetchMonixBackend.scala +++ b/effects/monix/src/main/scalajs/sttp/client4/impl/monix/FetchMonixBackend.scala @@ -65,7 +65,7 @@ class FetchMonixBackend private (fetchOptions: FetchOptions, customizeRequest: F override protected def compileWebSocketPipe( ws: WebSocket[Task], - pipe: Observable[WebSocketFrame.Data[_]] => Observable[WebSocketFrame] + pipe: Observable[WebSocketFrame.Data[?]] => Observable[WebSocketFrame] ): Task[Unit] = MonixWebSockets.compilePipe(ws, pipe) diff --git a/effects/monix/src/main/scalajvm/sttp/client4/httpclient/monix/HttpClientMonixBackend.scala b/effects/monix/src/main/scalajvm/sttp/client4/httpclient/monix/HttpClientMonixBackend.scala index d775fa7214..7a6bf4f269 100644 --- a/effects/monix/src/main/scalajvm/sttp/client4/httpclient/monix/HttpClientMonixBackend.scala +++ b/effects/monix/src/main/scalajvm/sttp/client4/httpclient/monix/HttpClientMonixBackend.scala @@ -132,7 +132,7 @@ object HttpClientMonixBackend { s: Scheduler ): WebSocketStreamBackend[Task, MonixStreams] = wrappers.FollowRedirectsBackend( - new HttpClientMonixBackend(client, closeClient, customizeRequest, compressionHandlers)(s) + new HttpClientMonixBackend(client, closeClient, customizeRequest, compressionHandlers) ) def apply( @@ -148,7 +148,7 @@ object HttpClientMonixBackend { closeClient = false, // we don't want to close Monix's scheduler customizeRequest, compressionHandlers - )(s) + ) ) def resource( @@ -169,7 +169,7 @@ object HttpClientMonixBackend { s: Scheduler = Scheduler.global ): Resource[Task, WebSocketStreamBackend[Task, MonixStreams]] = Resource.make( - Task.eval(HttpClientMonixBackend(client, closeClient = true, customizeRequest, compressionHandlers)(s)) + Task.eval(HttpClientMonixBackend(client, closeClient = true, customizeRequest, compressionHandlers)) )(_.close()) def usingClient( @@ -177,7 +177,7 @@ object HttpClientMonixBackend { customizeRequest: HttpRequest => HttpRequest = identity, compressionHandlers: CompressionHandlers[MonixStreams, MonixStreams.BinaryStream] = DefaultCompressionHandlers )(implicit s: Scheduler = Scheduler.global): WebSocketStreamBackend[Task, MonixStreams] = - HttpClientMonixBackend(client, closeClient = false, customizeRequest, compressionHandlers)(s) + HttpClientMonixBackend(client, closeClient = false, customizeRequest, compressionHandlers) /** Create a stub backend for testing, which uses the [[Task]] response wrapper, and supports `Observable[ByteBuffer]` * streaming. diff --git a/effects/monix/src/main/scalajvm/sttp/client4/httpclient/monix/MonixBodyFromHttpClient.scala b/effects/monix/src/main/scalajvm/sttp/client4/httpclient/monix/MonixBodyFromHttpClient.scala index 0e3ac75cb8..87d5666e68 100644 --- a/effects/monix/src/main/scalajvm/sttp/client4/httpclient/monix/MonixBodyFromHttpClient.scala +++ b/effects/monix/src/main/scalajvm/sttp/client4/httpclient/monix/MonixBodyFromHttpClient.scala @@ -21,7 +21,7 @@ private[monix] trait MonixBodyFromHttpClient extends BodyFromHttpClient[Task, Mo override def compileWebSocketPipe( ws: WebSocket[Task], - pipe: Observable[WebSocketFrame.Data[_]] => Observable[WebSocketFrame] + pipe: Observable[WebSocketFrame.Data[?]] => Observable[WebSocketFrame] ): Task[Unit] = MonixWebSockets.compilePipe(ws, pipe) @@ -54,7 +54,7 @@ private[monix] trait MonixBodyFromHttpClient extends BodyFromHttpClient[Task, Mo Task.pure((response, () => response.consumeWith(Consumer.complete).onErrorFallbackTo(Task.unit))) override protected def handleWS[T]( - responseAs: GenericWebSocketResponseAs[T, _], + responseAs: GenericWebSocketResponseAs[T, ?], meta: ResponseMetadata, ws: WebSocket[Task] ): Task[T] = bodyFromWs(responseAs, ws, meta) diff --git a/effects/monix/src/test/scalajs/sttp/client4/impl/monix/FetchMonixWebSocketTest.scala b/effects/monix/src/test/scalajs/sttp/client4/impl/monix/FetchMonixWebSocketTest.scala index 62e99e5c8e..4b06e9ca40 100644 --- a/effects/monix/src/test/scalajs/sttp/client4/impl/monix/FetchMonixWebSocketTest.scala +++ b/effects/monix/src/test/scalajs/sttp/client4/impl/monix/FetchMonixWebSocketTest.scala @@ -26,14 +26,14 @@ class FetchMonixWebSocketTest extends WebSocketTest[Task] with WebSocketStreamin override val streams: MonixStreams = MonixStreams override def prepend(item: WebSocketFrame.Text)( - to: streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] - ): streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] = + to: streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] + ): streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] = to.andThen(rest => Observable.now(item) ++ rest) - override def fromTextPipe(function: String => WebSocketFrame): streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] = + override def fromTextPipe(function: String => WebSocketFrame): streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] = MonixWebSockets.fromTextPipe(function) override def functionToPipe( - f: WebSocketFrame.Data[_] => Option[WebSocketFrame] - ): streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] = in => in.concatMapIterable(m => f(m).toList) + f: WebSocketFrame.Data[?] => Option[WebSocketFrame] + ): streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] = in => in.concatMapIterable(m => f(m).toList) } diff --git a/effects/monix/src/test/scalajvm/sttp/client4/impl/monix/HttpClientMonixWebSocketTest.scala b/effects/monix/src/test/scalajvm/sttp/client4/impl/monix/HttpClientMonixWebSocketTest.scala index 651b7552eb..77bb75c6cc 100644 --- a/effects/monix/src/test/scalajvm/sttp/client4/impl/monix/HttpClientMonixWebSocketTest.scala +++ b/effects/monix/src/test/scalajvm/sttp/client4/impl/monix/HttpClientMonixWebSocketTest.scala @@ -22,17 +22,17 @@ class HttpClientMonixWebSocketTest override val streams: MonixStreams = MonixStreams override def functionToPipe( - f: WebSocketFrame.Data[_] => Option[WebSocketFrame] - ): Observable[WebSocketFrame.Data[_]] => Observable[WebSocketFrame] = + f: WebSocketFrame.Data[?] => Option[WebSocketFrame] + ): Observable[WebSocketFrame.Data[?]] => Observable[WebSocketFrame] = in => in.concatMapIterable(m => f(m).toList) override def fromTextPipe( function: String => WebSocketFrame - ): Observable[WebSocketFrame.Data[_]] => Observable[WebSocketFrame] = MonixWebSockets.fromTextPipe(function) + ): Observable[WebSocketFrame.Data[?]] => Observable[WebSocketFrame] = MonixWebSockets.fromTextPipe(function) override def prepend(item: WebSocketFrame.Text)( - to: Observable[WebSocketFrame.Data[_]] => Observable[WebSocketFrame] - ): Observable[WebSocketFrame.Data[_]] => Observable[WebSocketFrame] = + to: Observable[WebSocketFrame.Data[?]] => Observable[WebSocketFrame] + ): Observable[WebSocketFrame.Data[?]] => Observable[WebSocketFrame] = to.andThen(rest => Observable.now(item) ++ rest) override def concurrently[T](fs: List[() => Task[T]]): Task[List[T]] = Task.parSequence(fs.map(_())) diff --git a/effects/monix/src/test/scalajvm/sttp/client4/impl/monix/MonixWebSocketsTest.scala b/effects/monix/src/test/scalajvm/sttp/client4/impl/monix/MonixWebSocketsTest.scala index 7ab035418f..ba85415f81 100644 --- a/effects/monix/src/test/scalajvm/sttp/client4/impl/monix/MonixWebSocketsTest.scala +++ b/effects/monix/src/test/scalajvm/sttp/client4/impl/monix/MonixWebSocketsTest.scala @@ -43,7 +43,7 @@ class MonixWebSocketsTest extends AnyFlatSpec with Matchers { } private def sentFrames(incoming: List[WebSocketFrame])( - pipe: Observable[WebSocketFrame.Data[_]] => Observable[WebSocketFrame] + pipe: Observable[WebSocketFrame.Data[?]] => Observable[WebSocketFrame] ): List[(WebSocketFrame, Boolean)] = { val ws = new RecordingWebSocket(incoming) MonixWebSockets.compilePipe(ws, pipe).runSyncUnsafe(5.seconds) @@ -51,8 +51,8 @@ class MonixWebSocketsTest extends AnyFlatSpec with Matchers { } // drains the incoming frames (as compilePipe requires), then emits the given frames - private def drainThen(frames: WebSocketFrame*): Observable[WebSocketFrame.Data[_]] => Observable[WebSocketFrame] = - in => Observable.fromTask(in.completedL).flatMap(_ => Observable(frames: _*)) + private def drainThen(frames: WebSocketFrame*): Observable[WebSocketFrame.Data[?]] => Observable[WebSocketFrame] = + in => Observable.fromTask(in.completedL).flatMap(_ => Observable(frames*)) it should "mark non-final fragments emitted by the pipe as continuations of the previous frame" in { val first = WebSocketFrame.Text("Hel", finalFragment = false, None) diff --git a/effects/zio/src/main/scala/sttp/client4/impl/zio/ExtendedEnvBackend.scala b/effects/zio/src/main/scala/sttp/client4/impl/zio/ExtendedEnvBackend.scala index 4e0f909554..8d63c7d997 100644 --- a/effects/zio/src/main/scala/sttp/client4/impl/zio/ExtendedEnvBackend.scala +++ b/effects/zio/src/main/scala/sttp/client4/impl/zio/ExtendedEnvBackend.scala @@ -7,19 +7,19 @@ import _root_.zio.{RIO, ZIO} import sttp.capabilities.Effect private abstract class ExtendedEnvBackend[R0, R1, P](delegate: GenericBackend[RIO[R0, *], P]) - extends GenericBackend[RIO[R0 with R1, *], P] { + extends GenericBackend[RIO[R0 & R1, *], P] { override def send[T]( - request: GenericRequest[T, P with Effect[RIO[R0 with R1, *]]] - ): RIO[R0 with R1, Response[T]] = + request: GenericRequest[T, P & Effect[RIO[R0 & R1, *]]] + ): RIO[R0 & R1, Response[T]] = for { - env <- ZIO.environment[R0 with R1] - mappedRequest = MapEffect[RIO[R0 with R1, *], RIO[R0, *], T, P]( + env <- ZIO.environment[R0 & R1] + mappedRequest = MapEffect[RIO[R0 & R1, *], RIO[R0, *], T, P]( request, - new FunctionK[RIO[R0 with R1, *], RIO[R0, *]] { - override def apply[A](fa: => RIO[R0 with R1, A]): RIO[R0, A] = fa.provideEnvironment(env) + new FunctionK[RIO[R0 & R1, *], RIO[R0, *]] { + override def apply[A](fa: => RIO[R0 & R1, A]): RIO[R0, A] = fa.provideEnvironment(env) }, - new FunctionK[RIO[R0, *], RIO[R0 with R1, *]] { - override def apply[A](fa: => RIO[R0, A]): RIO[R0 with R1, A] = fa + new FunctionK[RIO[R0, *], RIO[R0 & R1, *]] { + override def apply[A](fa: => RIO[R0, A]): RIO[R0 & R1, A] = fa }, monad, delegate.monad @@ -27,7 +27,7 @@ private abstract class ExtendedEnvBackend[R0, R1, P](delegate: GenericBackend[RI resp <- delegate.send(mappedRequest) } yield resp - override def close(): RIO[R0 with R1, Unit] = delegate.close() + override def close(): RIO[R0 & R1, Unit] = delegate.close() - override val monad: MonadError[RIO[R0 with R1, *]] = new RIOMonadAsyncError[R0 with R1] + override val monad: MonadError[RIO[R0 & R1, *]] = new RIOMonadAsyncError[R0 & R1] } diff --git a/effects/zio/src/main/scala/sttp/client4/impl/zio/ZioWebSockets.scala b/effects/zio/src/main/scala/sttp/client4/impl/zio/ZioWebSockets.scala index b69a67fa0d..266a2646bb 100644 --- a/effects/zio/src/main/scala/sttp/client4/impl/zio/ZioWebSockets.scala +++ b/effects/zio/src/main/scala/sttp/client4/impl/zio/ZioWebSockets.scala @@ -7,14 +7,14 @@ import zio.{Ref, ZIO} object ZioWebSockets { def compilePipe[R]( ws: WebSocket[ZIO[R, Throwable, *]], - pipe: ZStream[R, Throwable, WebSocketFrame.Data[_]] => ZStream[R, Throwable, WebSocketFrame] + pipe: ZStream[R, Throwable, WebSocketFrame.Data[?]] => ZStream[R, Throwable, WebSocketFrame] ): ZIO[R, Throwable, Unit] = for { closeRef <- Ref.make(Option.empty[WebSocketFrame.Close]) closeSent <- Ref.make(false) // set the close to echo (a received Close) or none (the connection is already gone), then terminate the stream onClose = (close: Option[WebSocketFrame.Close]) => - ZStream.fromZIO(closeRef.set(close).as(Option.empty[WebSocketFrame.Data[_]])) + ZStream.fromZIO(closeRef.set(close).as(Option.empty[WebSocketFrame.Data[?]])) _ <- pipe( ZStream diff --git a/effects/zio/src/main/scalajs/sttp/client4/impl/zio/FetchZioBackend.scala b/effects/zio/src/main/scalajs/sttp/client4/impl/zio/FetchZioBackend.scala index f59b99f9f1..4054656dde 100644 --- a/effects/zio/src/main/scalajs/sttp/client4/impl/zio/FetchZioBackend.scala +++ b/effects/zio/src/main/scalajs/sttp/client4/impl/zio/FetchZioBackend.scala @@ -67,7 +67,7 @@ class FetchZioBackend private (fetchOptions: FetchOptions, customizeRequest: Fet override protected def compileWebSocketPipe( ws: WebSocket[Task], - pipe: Observable[WebSocketFrame.Data[_]] => Observable[WebSocketFrame] + pipe: Observable[WebSocketFrame.Data[?]] => Observable[WebSocketFrame] ): Task[Unit] = ZioWebSockets.compilePipe(ws, pipe) diff --git a/effects/zio/src/main/scalajs/sttp/client4/impl/zio/package.scala b/effects/zio/src/main/scalajs/sttp/client4/impl/zio/package.scala index 38ef42799d..1455d1dc4e 100644 --- a/effects/zio/src/main/scalajs/sttp/client4/impl/zio/package.scala +++ b/effects/zio/src/main/scalajs/sttp/client4/impl/zio/package.scala @@ -8,23 +8,23 @@ import sttp.client4._ package object zio { implicit class BackendExtendEnv[R0](delegate: Backend[RIO[R0, *]]) { - def extendEnv[R1]: Backend[RIO[R0 with R1, *]] = - new ExtendedEnvBackend[R0, R1, Any](delegate) with Backend[RIO[R0 with R1, *]] {} + def extendEnv[R1]: Backend[RIO[R0 & R1, *]] = + new ExtendedEnvBackend[R0, R1, Any](delegate) with Backend[RIO[R0 & R1, *]] {} } implicit class WebSocketBackendExtendEnv[R0](delegate: WebSocketBackend[RIO[R0, *]]) { - def extendEnv[R1]: WebSocketBackend[RIO[R0 with R1, *]] = - new ExtendedEnvBackend[R0, R1, WebSockets](delegate) with WebSocketBackend[RIO[R0 with R1, *]] {} + def extendEnv[R1]: WebSocketBackend[RIO[R0 & R1, *]] = + new ExtendedEnvBackend[R0, R1, WebSockets](delegate) with WebSocketBackend[RIO[R0 & R1, *]] {} } implicit class StreamBackendExtendEnv[R0, S](delegate: StreamBackend[RIO[R0, *], S]) { - def extendEnv[R1]: StreamBackend[RIO[R0 with R1, *], S] = - new ExtendedEnvBackend[R0, R1, S](delegate) with StreamBackend[RIO[R0 with R1, *], S] {} + def extendEnv[R1]: StreamBackend[RIO[R0 & R1, *], S] = + new ExtendedEnvBackend[R0, R1, S](delegate) with StreamBackend[RIO[R0 & R1, *], S] {} } implicit class WebSocketStreamBackendExtendEnv[R0, S](delegate: WebSocketStreamBackend[RIO[R0, *], S]) { - def extendEnv[R1]: WebSocketStreamBackend[RIO[R0 with R1, *], S] = - new ExtendedEnvBackend[R0, R1, S with WebSockets](delegate) with WebSocketStreamBackend[RIO[R0 with R1, *], S] {} + def extendEnv[R1]: WebSocketStreamBackend[RIO[R0 & R1, *], S] = + new ExtendedEnvBackend[R0, R1, S & WebSockets](delegate) with WebSocketStreamBackend[RIO[R0 & R1, *], S] {} } /** Type alias to be used as the sttp ZIO service (mainly in ZIO environment). */ @@ -55,7 +55,7 @@ package object zio { * [[Request.response]]). Or a failed effect, if an exception occurred when connecting to the target host, writing * the request or reading the response. */ - def send[T, C >: ZioStreams with Effect[Task]]( + def send[T, C >: ZioStreams & Effect[Task]]( request: StreamRequest[T, C] ): ZIO[SttpClient, Throwable, Response[T]] = ZIO.serviceWithZIO[SttpClient](request.send[Task, ZioStreams]) @@ -63,9 +63,9 @@ package object zio { /** A variant of [[send]] which allows the effects that are part of the response handling specification (when using * resource-safe streaming) to use an `R` environment. */ - def sendR[T, C >: ZioStreams with Effect[RIO[R, *]], R]( + def sendR[T, C >: ZioStreams & Effect[RIO[R, *]], R]( request: StreamRequest[T, C] - ): ZIO[SttpClient with R, Throwable, Response[T]] = { + ): ZIO[SttpClient & R, Throwable, Response[T]] = { import sttp.client4.impl.zio.StreamBackendExtendEnv ZIO.serviceWithZIO[SttpClient](b => request.send[RIO[R, *], ZioStreams](b.extendEnv[R])) } @@ -87,7 +87,7 @@ package object zio { /** A variant of [[send]] which allows the effects that are part of the response handling specification (when using * websockets or resource-safe streaming) to use an `R` environment. */ - def sendR[T, R](request: WebSocketRequest[RIO[R, *], T]): ZIO[SttpClient with R, Throwable, Response[T]] = { + def sendR[T, R](request: WebSocketRequest[RIO[R, *], T]): ZIO[SttpClient & R, Throwable, Response[T]] = { import sttp.client4.impl.zio.WebSocketBackendExtendEnv ZIO.serviceWithZIO[SttpClient](b => request.send(b.extendEnv[R])) } diff --git a/effects/zio/src/main/scalajvm/sttp/client4/httpclient/zio/ZioBodyFromHttpClient.scala b/effects/zio/src/main/scalajvm/sttp/client4/httpclient/zio/ZioBodyFromHttpClient.scala index f56ffac366..8d36af12e4 100644 --- a/effects/zio/src/main/scalajvm/sttp/client4/httpclient/zio/ZioBodyFromHttpClient.scala +++ b/effects/zio/src/main/scalajvm/sttp/client4/httpclient/zio/ZioBodyFromHttpClient.scala @@ -20,7 +20,7 @@ private[zio] class ZioBodyFromHttpClient extends BodyFromHttpClient[Task, ZioStr override def compileWebSocketPipe( ws: WebSocket[Task], - pipe: ZStream[Any, Throwable, WebSocketFrame.Data[_]] => ZStream[Any, Throwable, WebSocketFrame] + pipe: ZStream[Any, Throwable, WebSocketFrame.Data[?]] => ZStream[Any, Throwable, WebSocketFrame] ): Task[Unit] = ZioWebSockets.compilePipe(ws, pipe) override protected def bodyFromResponseAs: BodyFromResponseAs[Task, ZStream[ @@ -63,7 +63,7 @@ private[zio] class ZioBodyFromHttpClient extends BodyFromHttpClient[Task, ZioStr ZIO.succeed((response, () => response.runDrain.catchAll(_ => ZIO.unit))) override protected def handleWS[T]( - responseAs: GenericWebSocketResponseAs[T, _], + responseAs: GenericWebSocketResponseAs[T, ?], meta: ResponseMetadata, ws: WebSocket[Task] ): Task[T] = bodyFromWs(responseAs, ws, meta) diff --git a/effects/zio/src/main/scalajvm/sttp/client4/httpclient/zio/package.scala b/effects/zio/src/main/scalajvm/sttp/client4/httpclient/zio/package.scala index 2f4efb36b3..3a088cc8b4 100644 --- a/effects/zio/src/main/scalajvm/sttp/client4/httpclient/zio/package.scala +++ b/effects/zio/src/main/scalajvm/sttp/client4/httpclient/zio/package.scala @@ -35,7 +35,7 @@ package object zio { * [[Request.response]]). Or a failed effect, if an exception occurred when connecting to the target host, writing * the request or reading the response. */ - def send[T, C >: ZioStreams with Effect[Task]]( + def send[T, C >: ZioStreams & Effect[Task]]( request: StreamRequest[T, C] ): ZIO[SttpClient, Throwable, Response[T]] = ZIO.serviceWithZIO[SttpClient](request.send[Task, ZioStreams]) @@ -43,9 +43,9 @@ package object zio { /** A variant of [[send]] which allows the effects that are part of the response handling specification (when using * resource-safe streaming) to use an `R` environment. */ - def sendR[T, C >: ZioStreams with Effect[RIO[R, *]], R]( + def sendR[T, C >: ZioStreams & Effect[RIO[R, *]], R]( request: StreamRequest[T, C] - ): ZIO[SttpClient with R, Throwable, Response[T]] = { + ): ZIO[SttpClient & R, Throwable, Response[T]] = { import sttp.client4.impl.zio.StreamBackendExtendEnv ZIO.serviceWithZIO[SttpClient](b => request.send[RIO[R, *], ZioStreams](b.extendEnv[R])) } @@ -67,7 +67,7 @@ package object zio { /** A variant of [[send]] which allows the effects that are part of the response handling specification (when using * websockets or resource-safe streaming) to use an `R` environment. */ - def sendR[T, R](request: WebSocketRequest[RIO[R, *], T]): ZIO[SttpClient with R, Throwable, Response[T]] = { + def sendR[T, R](request: WebSocketRequest[RIO[R, *], T]): ZIO[SttpClient & R, Throwable, Response[T]] = { import sttp.client4.impl.zio.WebSocketBackendExtendEnv ZIO.serviceWithZIO[SttpClient](b => request.send(b.extendEnv[R])) } diff --git a/effects/zio/src/main/scalajvm/sttp/client4/impl/zio/package.scala b/effects/zio/src/main/scalajvm/sttp/client4/impl/zio/package.scala index 6932c8a2f9..656920621c 100644 --- a/effects/zio/src/main/scalajvm/sttp/client4/impl/zio/package.scala +++ b/effects/zio/src/main/scalajvm/sttp/client4/impl/zio/package.scala @@ -6,22 +6,22 @@ import sttp.client4.{Backend, StreamBackend, WebSocketBackend, WebSocketStreamBa package object zio { implicit class BackendExtendEnv[R0](delegate: Backend[RIO[R0, *]]) { - def extendEnv[R1]: Backend[RIO[R0 with R1, *]] = - new ExtendedEnvBackend[R0, R1, Any](delegate) with Backend[RIO[R0 with R1, *]] {} + def extendEnv[R1]: Backend[RIO[R0 & R1, *]] = + new ExtendedEnvBackend[R0, R1, Any](delegate) with Backend[RIO[R0 & R1, *]] {} } implicit class WebSocketBackendExtendEnv[R0](delegate: WebSocketBackend[RIO[R0, *]]) { - def extendEnv[R1]: WebSocketBackend[RIO[R0 with R1, *]] = - new ExtendedEnvBackend[R0, R1, WebSockets](delegate) with WebSocketBackend[RIO[R0 with R1, *]] {} + def extendEnv[R1]: WebSocketBackend[RIO[R0 & R1, *]] = + new ExtendedEnvBackend[R0, R1, WebSockets](delegate) with WebSocketBackend[RIO[R0 & R1, *]] {} } implicit class StreamBackendExtendEnv[R0, S](delegate: StreamBackend[RIO[R0, *], S]) { - def extendEnv[R1]: StreamBackend[RIO[R0 with R1, *], S] = - new ExtendedEnvBackend[R0, R1, S](delegate) with StreamBackend[RIO[R0 with R1, *], S] {} + def extendEnv[R1]: StreamBackend[RIO[R0 & R1, *], S] = + new ExtendedEnvBackend[R0, R1, S](delegate) with StreamBackend[RIO[R0 & R1, *], S] {} } implicit class WebSocketStreamBackendExtendEnv[R0, S](delegate: WebSocketStreamBackend[RIO[R0, *], S]) { - def extendEnv[R1]: WebSocketStreamBackend[RIO[R0 with R1, *], S] = - new ExtendedEnvBackend[R0, R1, S with WebSockets](delegate) with WebSocketStreamBackend[RIO[R0 with R1, *], S] {} + def extendEnv[R1]: WebSocketStreamBackend[RIO[R0 & R1, *], S] = + new ExtendedEnvBackend[R0, R1, S & WebSockets](delegate) with WebSocketStreamBackend[RIO[R0 & R1, *], S] {} } } diff --git a/effects/zio/src/test/scalajs/sttp/client4/impl/zio/FetchZioStreamingTest.scala b/effects/zio/src/test/scalajs/sttp/client4/impl/zio/FetchZioStreamingTest.scala index 8eecf0f644..f209edd7cd 100644 --- a/effects/zio/src/test/scalajs/sttp/client4/impl/zio/FetchZioStreamingTest.scala +++ b/effects/zio/src/test/scalajs/sttp/client4/impl/zio/FetchZioStreamingTest.scala @@ -17,7 +17,7 @@ class FetchZioStreamingTest extends StreamingTest[Task, ZioStreams] with ZioTest override implicit val convertToFuture: ConvertToFuture[Task] = convertZioTaskToFuture override def bodyProducer(chunks: Iterable[Array[Byte]]): ZStream[Any, Throwable, Byte] = - ZStream.fromChunks(chunks.map(Chunk.fromArray).toSeq: _*) + ZStream.fromChunks(chunks.map(Chunk.fromArray).toSeq*) override def bodyConsumer(stream: ZStream[Any, Throwable, Byte]): Task[String] = stream.runCollect.map(bytes => new String(bytes.toArray, Utf8)) diff --git a/effects/zio/src/test/scalajs/sttp/client4/impl/zio/FetchZioWebSocketTest.scala b/effects/zio/src/test/scalajs/sttp/client4/impl/zio/FetchZioWebSocketTest.scala index dfc0b21fa6..4e7d901a6e 100644 --- a/effects/zio/src/test/scalajs/sttp/client4/impl/zio/FetchZioWebSocketTest.scala +++ b/effects/zio/src/test/scalajs/sttp/client4/impl/zio/FetchZioWebSocketTest.scala @@ -26,14 +26,14 @@ class FetchZioWebSocketTest extends WebSocketTest[Task] with WebSocketStreamingT override val streams: ZioStreams = ZioStreams override def prepend(item: WebSocketFrame.Text)( - to: streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] - ): streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] = + to: streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] + ): streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] = to.andThen(rest => ZStream.succeed(item) ++ rest) - override def fromTextPipe(function: String => WebSocketFrame): streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] = + override def fromTextPipe(function: String => WebSocketFrame): streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] = ZioWebSockets.fromTextPipe(function) override def functionToPipe( - f: WebSocketFrame.Data[_] => Option[WebSocketFrame] - ): streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] = in => in.mapConcat(m => f(m).toList) + f: WebSocketFrame.Data[?] => Option[WebSocketFrame] + ): streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] = in => in.mapConcat(m => f(m).toList) } diff --git a/effects/zio/src/test/scalajvm/sttp/client4/httpclient/zio/HttpClientZioStreamingTest.scala b/effects/zio/src/test/scalajvm/sttp/client4/httpclient/zio/HttpClientZioStreamingTest.scala index 422bd5f692..177a5759cf 100644 --- a/effects/zio/src/test/scalajvm/sttp/client4/httpclient/zio/HttpClientZioStreamingTest.scala +++ b/effects/zio/src/test/scalajvm/sttp/client4/httpclient/zio/HttpClientZioStreamingTest.scala @@ -18,7 +18,7 @@ class HttpClientZioStreamingTest extends StreamingTest[Task, ZioStreams] with Zi override implicit val convertToFuture: ConvertToFuture[Task] = convertZioTaskToFuture override def bodyProducer(chunks: Iterable[Array[Byte]]): ZStream[Any, Throwable, Byte] = - ZStream.fromChunks(chunks.map(Chunk.fromArray).toSeq: _*) + ZStream.fromChunks(chunks.map(Chunk.fromArray).toSeq*) override def bodyConsumer(stream: ZStream[Any, Throwable, Byte]): Task[String] = stream.runCollect.map(bytes => new String(bytes.toArray, Utf8)) diff --git a/effects/zio/src/test/scalajvm/sttp/client4/httpclient/zio/HttpClientZioWebSocketTest.scala b/effects/zio/src/test/scalajvm/sttp/client4/httpclient/zio/HttpClientZioWebSocketTest.scala index d02106b236..706a2de47b 100644 --- a/effects/zio/src/test/scalajvm/sttp/client4/httpclient/zio/HttpClientZioWebSocketTest.scala +++ b/effects/zio/src/test/scalajvm/sttp/client4/httpclient/zio/HttpClientZioWebSocketTest.scala @@ -22,18 +22,18 @@ class HttpClientZioWebSocketTest override val streams: ZioStreams = ZioStreams override def functionToPipe( - f: WebSocketFrame.Data[_] => Option[WebSocketFrame] - ): ZioStreams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] = + f: WebSocketFrame.Data[?] => Option[WebSocketFrame] + ): ZioStreams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] = in => in.mapConcat(m => f(m).toList) override def fromTextPipe( function: String => WebSocketFrame - ): ZioStreams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] = + ): ZioStreams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] = ZioWebSockets.fromTextPipe[Any](function) override def prepend(item: WebSocketFrame.Text)( - to: PipeR[Any, WebSocketFrame.Data[_], WebSocketFrame] - ): ZioStreams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] = + to: PipeR[Any, WebSocketFrame.Data[?], WebSocketFrame] + ): ZioStreams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] = to.andThen(rest => ZStream(item) ++ rest) override def concurrently[T](fs: List[() => Task[T]]): Task[List[T]] = ZIO.collectAllPar(fs.map(_())) diff --git a/effects/zio/src/test/scalajvm/sttp/client4/impl/zio/ZioWebSocketsTest.scala b/effects/zio/src/test/scalajvm/sttp/client4/impl/zio/ZioWebSocketsTest.scala index 76ada4d59f..b031319932 100644 --- a/effects/zio/src/test/scalajvm/sttp/client4/impl/zio/ZioWebSocketsTest.scala +++ b/effects/zio/src/test/scalajvm/sttp/client4/impl/zio/ZioWebSocketsTest.scala @@ -36,7 +36,7 @@ class ZioWebSocketsTest extends AnyFlatSpec with Matchers with ZioTestBase { } private def sentFrames(incoming: List[WebSocketFrame])( - pipe: ZStream[Any, Throwable, WebSocketFrame.Data[_]] => ZStream[Any, Throwable, WebSocketFrame] + pipe: ZStream[Any, Throwable, WebSocketFrame.Data[?]] => ZStream[Any, Throwable, WebSocketFrame] ): List[(WebSocketFrame, Boolean)] = unsafeRunSyncOrThrow(for { incomingRef <- Ref.make(incoming) diff --git a/effects/zio1/src/main/scala/sttp/client4/impl/zio/ExtendedEnvBackend.scala b/effects/zio1/src/main/scala/sttp/client4/impl/zio/ExtendedEnvBackend.scala index 3c7957189a..c0dfeb6fda 100644 --- a/effects/zio1/src/main/scala/sttp/client4/impl/zio/ExtendedEnvBackend.scala +++ b/effects/zio1/src/main/scala/sttp/client4/impl/zio/ExtendedEnvBackend.scala @@ -7,19 +7,19 @@ import _root_.zio.{RIO, ZIO} import sttp.capabilities.Effect private abstract class ExtendedEnvBackend[R0, R1, P](delegate: GenericBackend[RIO[R0, *], P]) - extends GenericBackend[RIO[R0 with R1, *], P] { + extends GenericBackend[RIO[R0 & R1, *], P] { override def send[T]( - request: GenericRequest[T, P with Effect[RIO[R0 with R1, *]]] - ): RIO[R0 with R1, Response[T]] = + request: GenericRequest[T, P & Effect[RIO[R0 & R1, *]]] + ): RIO[R0 & R1, Response[T]] = for { - env <- ZIO.environment[R0 with R1] - mappedRequest = MapEffect[RIO[R0 with R1, *], RIO[R0, *], T, P]( + env <- ZIO.environment[R0 & R1] + mappedRequest = MapEffect[RIO[R0 & R1, *], RIO[R0, *], T, P]( request, - new FunctionK[RIO[R0 with R1, *], RIO[R0, *]] { - override def apply[A](fa: => RIO[R0 with R1, A]): RIO[R0, A] = fa.provide(env) + new FunctionK[RIO[R0 & R1, *], RIO[R0, *]] { + override def apply[A](fa: => RIO[R0 & R1, A]): RIO[R0, A] = fa.provide(env) }, - new FunctionK[RIO[R0, *], RIO[R0 with R1, *]] { - override def apply[A](fa: => RIO[R0, A]): RIO[R0 with R1, A] = fa + new FunctionK[RIO[R0, *], RIO[R0 & R1, *]] { + override def apply[A](fa: => RIO[R0, A]): RIO[R0 & R1, A] = fa }, monad, delegate.monad @@ -27,7 +27,7 @@ private abstract class ExtendedEnvBackend[R0, R1, P](delegate: GenericBackend[RI resp <- delegate.send(mappedRequest) } yield resp - override def close(): RIO[R0 with R1, Unit] = delegate.close() + override def close(): RIO[R0 & R1, Unit] = delegate.close() - override val monad: MonadError[RIO[R0 with R1, *]] = new RIOMonadAsyncError[R0 with R1] + override val monad: MonadError[RIO[R0 & R1, *]] = new RIOMonadAsyncError[R0 & R1] } diff --git a/effects/zio1/src/main/scala/sttp/client4/impl/zio/SttpClientStubbingBase.scala b/effects/zio1/src/main/scala/sttp/client4/impl/zio/SttpClientStubbingBase.scala index d9581c5802..69c8f60add 100644 --- a/effects/zio1/src/main/scala/sttp/client4/impl/zio/SttpClientStubbingBase.scala +++ b/effects/zio1/src/main/scala/sttp/client4/impl/zio/SttpClientStubbingBase.scala @@ -23,7 +23,7 @@ trait AbstractClientStubbing[R, P] { trait Service { def whenRequestMatchesPartial( - partial: PartialFunction[GenericRequest[_, _], Response[StubBody]] + partial: PartialFunction[GenericRequest[?, ?], Response[StubBody]] ): URIO[SttpClientStubbing, Unit] private[zio] def update(f: BackendStub => BackendStub): UIO[Unit] @@ -31,14 +31,14 @@ trait AbstractClientStubbing[R, P] { private[sttp] class StubWrapper(stub: Ref[BackendStub]) extends Service { override def whenRequestMatchesPartial( - partial: PartialFunction[GenericRequest[_, _], Response[StubBody]] + partial: PartialFunction[GenericRequest[?, ?], Response[StubBody]] ): URIO[SttpClientStubbing, Unit] = update(_.whenRequestMatchesPartial(partial)) override private[zio] def update(f: BackendStub => BackendStub) = stub.update(f) } - case class StubbingWhenRequest private[sttp] (p: GenericRequest[_, _] => Boolean) { + case class StubbingWhenRequest private[sttp] (p: GenericRequest[?, ?] => Boolean) { implicit val _serviceTag: Tag[Service] = serviceTag val thenRespondOk: URIO[SttpClientStubbing, Unit] = whenRequest(_.whenRequestMatches(p).thenRespondOk(): BackendStub) @@ -62,19 +62,19 @@ trait AbstractClientStubbing[R, P] { whenRequest(_.whenRequestMatches(p).thenRespond(resp)) def thenRespondCyclic[T](responses: Response[StubBody]*): URIO[SttpClientStubbing, Unit] = - whenRequest(_.whenRequestMatches(p).thenRespondCyclic(responses: _*)) + whenRequest(_.whenRequestMatches(p).thenRespondCyclic(responses*)) def thenRespondF(resp: => RIO[R, Response[StubBody]]): URIO[SttpClientStubbing, Unit] = whenRequest(_.whenRequestMatches(p).thenRespondF(resp)) - def thenRespondF(resp: GenericRequest[_, _] => RIO[R, Response[StubBody]]): URIO[SttpClientStubbing, Unit] = + def thenRespondF(resp: GenericRequest[?, ?] => RIO[R, Response[StubBody]]): URIO[SttpClientStubbing, Unit] = whenRequest(_.whenRequestMatches(p).thenRespondF(resp)) private def whenRequest(f: BackendStub => BackendStub): URIO[SttpClientStubbing, Unit] = URIO.serviceWith(_.update(f)) } - val layer: ZLayer[Any, Nothing, Has[Service] with Has[Backend]] = { + val layer: ZLayer[Any, Nothing, Has[Service] & Has[Backend]] = { implicit val _serviceTag: Tag[Service] = serviceTag implicit val _backendTag: Tag[Backend] = sttpBackendTag @@ -93,7 +93,7 @@ trait StreamClientStubbing[R, P] extends AbstractClientStubbing[R, P] { def backendStub: StreamBackendStub[RIO[R, *], P] = StreamBackendStub(monad) def proxy(stub: Ref[StreamBackendStub[RIO[R, *], P]]): StreamBackend[RIO[R, *], P] = new StreamBackend[RIO[R, *], P] { - def send[T](request: GenericRequest[T, P with Effect[RIO[R, *]]]): RIO[R, Response[T]] = + def send[T](request: GenericRequest[T, P & Effect[RIO[R, *]]]): RIO[R, Response[T]] = stub.get >>= (_.send(request)) def close(): RIO[R, Unit] = stub.get >>= (_.close()) @@ -102,7 +102,7 @@ trait StreamClientStubbing[R, P] extends AbstractClientStubbing[R, P] { } } -trait WebSocketStreamClientStubbing[R, P] extends AbstractClientStubbing[R, P with WebSockets] { +trait WebSocketStreamClientStubbing[R, P] extends AbstractClientStubbing[R, P & WebSockets] { type Backend = WebSocketStreamBackend[RIO[R, *], P] type BackendStub = WebSocketStreamBackendStub[RIO[R, *], P] @@ -111,7 +111,7 @@ trait WebSocketStreamClientStubbing[R, P] extends AbstractClientStubbing[R, P wi def proxy(stub: Ref[WebSocketStreamBackendStub[RIO[R, *], P]]): WebSocketStreamBackend[RIO[R, *], P] = new WebSocketStreamBackend[RIO[R, *], P] { def send[T]( - request: GenericRequest[T, P with WebSockets with Effect[RIO[R, *]]] + request: GenericRequest[T, P & WebSockets & Effect[RIO[R, *]]] ): RIO[R, Response[T]] = stub.get >>= (_.send(request)) def close(): RIO[R, Unit] = diff --git a/effects/zio1/src/main/scala/sttp/client4/impl/zio/ZioWebSockets.scala b/effects/zio1/src/main/scala/sttp/client4/impl/zio/ZioWebSockets.scala index 7d3e7482a8..809ca9f904 100644 --- a/effects/zio1/src/main/scala/sttp/client4/impl/zio/ZioWebSockets.scala +++ b/effects/zio1/src/main/scala/sttp/client4/impl/zio/ZioWebSockets.scala @@ -7,14 +7,14 @@ import zio.{Ref, ZIO} object ZioWebSockets { def compilePipe[R]( ws: WebSocket[ZIO[R, Throwable, *]], - pipe: ZStream[R, Throwable, WebSocketFrame.Data[_]] => ZStream[R, Throwable, WebSocketFrame] + pipe: ZStream[R, Throwable, WebSocketFrame.Data[?]] => ZStream[R, Throwable, WebSocketFrame] ): ZIO[R, Throwable, Unit] = for { closeRef <- Ref.make(Option.empty[WebSocketFrame.Close]) closeSent <- Ref.make(false) // set the close to echo (a received Close) or none (the connection is already gone), then terminate the stream onClose = (close: Option[WebSocketFrame.Close]) => - Stream.fromEffect(closeRef.set(close).as(Option.empty[WebSocketFrame.Data[_]])) + Stream.fromEffect(closeRef.set(close).as(Option.empty[WebSocketFrame.Data[?]])) _ <- pipe( Stream diff --git a/effects/zio1/src/main/scala/sttp/client4/impl/zio/package.scala b/effects/zio1/src/main/scala/sttp/client4/impl/zio/package.scala index 5184ba29f0..5014c1d8f9 100644 --- a/effects/zio1/src/main/scala/sttp/client4/impl/zio/package.scala +++ b/effects/zio1/src/main/scala/sttp/client4/impl/zio/package.scala @@ -6,22 +6,22 @@ import _root_.zio.RIO package object zio { implicit class BackendExtendEnv[R0](delegate: Backend[RIO[R0, *]]) { - def extendEnv[R1]: Backend[RIO[R0 with R1, *]] = - new ExtendedEnvBackend[R0, R1, Any](delegate) with Backend[RIO[R0 with R1, *]] {} + def extendEnv[R1]: Backend[RIO[R0 & R1, *]] = + new ExtendedEnvBackend[R0, R1, Any](delegate) with Backend[RIO[R0 & R1, *]] {} } implicit class WebSocketBackendExtendEnv[R0](delegate: WebSocketBackend[RIO[R0, *]]) { - def extendEnv[R1]: WebSocketBackend[RIO[R0 with R1, *]] = - new ExtendedEnvBackend[R0, R1, WebSockets](delegate) with WebSocketBackend[RIO[R0 with R1, *]] {} + def extendEnv[R1]: WebSocketBackend[RIO[R0 & R1, *]] = + new ExtendedEnvBackend[R0, R1, WebSockets](delegate) with WebSocketBackend[RIO[R0 & R1, *]] {} } implicit class StreamBackendExtendEnv[R0, S](delegate: StreamBackend[RIO[R0, *], S]) { - def extendEnv[R1]: StreamBackend[RIO[R0 with R1, *], S] = - new ExtendedEnvBackend[R0, R1, S](delegate) with StreamBackend[RIO[R0 with R1, *], S] {} + def extendEnv[R1]: StreamBackend[RIO[R0 & R1, *], S] = + new ExtendedEnvBackend[R0, R1, S](delegate) with StreamBackend[RIO[R0 & R1, *], S] {} } implicit class WebSocketStreamBackendExtendEnv[R0, S](delegate: WebSocketStreamBackend[RIO[R0, *], S]) { - def extendEnv[R1]: WebSocketStreamBackend[RIO[R0 with R1, *], S] = - new ExtendedEnvBackend[R0, R1, S with WebSockets](delegate) with WebSocketStreamBackend[RIO[R0 with R1, *], S] {} + def extendEnv[R1]: WebSocketStreamBackend[RIO[R0 & R1, *], S] = + new ExtendedEnvBackend[R0, R1, S & WebSockets](delegate) with WebSocketStreamBackend[RIO[R0 & R1, *], S] {} } } diff --git a/effects/zio1/src/main/scalajs/sttp/client4/impl/zio/FetchZioBackend.scala b/effects/zio1/src/main/scalajs/sttp/client4/impl/zio/FetchZioBackend.scala index 8712d48c30..7945e1a7e6 100644 --- a/effects/zio1/src/main/scalajs/sttp/client4/impl/zio/FetchZioBackend.scala +++ b/effects/zio1/src/main/scalajs/sttp/client4/impl/zio/FetchZioBackend.scala @@ -72,7 +72,7 @@ class FetchZioBackend private (fetchOptions: FetchOptions, customizeRequest: Fet override protected def compileWebSocketPipe( ws: WebSocket[Task], - pipe: Observable[WebSocketFrame.Data[_]] => Observable[WebSocketFrame] + pipe: Observable[WebSocketFrame.Data[?]] => Observable[WebSocketFrame] ): Task[Unit] = ZioWebSockets.compilePipe(ws, pipe) diff --git a/effects/zio1/src/main/scalajvm/sttp/client4/httpclient/zio/HttpClientZioBackend.scala b/effects/zio1/src/main/scalajvm/sttp/client4/httpclient/zio/HttpClientZioBackend.scala index 96c5123b85..de042c25ba 100644 --- a/effects/zio1/src/main/scalajvm/sttp/client4/httpclient/zio/HttpClientZioBackend.scala +++ b/effects/zio1/src/main/scalajvm/sttp/client4/httpclient/zio/HttpClientZioBackend.scala @@ -222,5 +222,5 @@ object HttpClientZioBackend { */ def stub: WebSocketStreamBackendStub[Task, ZioStreams] = WebSocketStreamBackendStub(new RIOMonadAsyncError[Any]) - val stubLayer: ZLayer[Any, Nothing, SttpClientStubbing with SttpClient] = SttpClientStubbing.layer + val stubLayer: ZLayer[Any, Nothing, SttpClientStubbing & SttpClient] = SttpClientStubbing.layer } diff --git a/effects/zio1/src/main/scalajvm/sttp/client4/httpclient/zio/ZioBodyFromHttpClient.scala b/effects/zio1/src/main/scalajvm/sttp/client4/httpclient/zio/ZioBodyFromHttpClient.scala index d05e6c35ac..98ac087446 100644 --- a/effects/zio1/src/main/scalajvm/sttp/client4/httpclient/zio/ZioBodyFromHttpClient.scala +++ b/effects/zio1/src/main/scalajvm/sttp/client4/httpclient/zio/ZioBodyFromHttpClient.scala @@ -22,7 +22,7 @@ private[zio] class ZioBodyFromHttpClient extends BodyFromHttpClient[Task, ZioStr override def compileWebSocketPipe( ws: WebSocket[Task], - pipe: ZStream[Any, Throwable, WebSocketFrame.Data[_]] => ZStream[Any, Throwable, WebSocketFrame] + pipe: ZStream[Any, Throwable, WebSocketFrame.Data[?]] => ZStream[Any, Throwable, WebSocketFrame] ): Task[Unit] = ZioWebSockets.compilePipe(ws, pipe) override protected def bodyFromResponseAs: BodyFromResponseAs[Task, ZStream[ @@ -88,7 +88,7 @@ private[zio] class ZioBodyFromHttpClient extends BodyFromHttpClient[Task, ZioStr Task.succeed((response, () => response.runDrain.catchAll(_ => ZIO.unit))) override protected def handleWS[T]( - responseAs: GenericWebSocketResponseAs[T, _], + responseAs: GenericWebSocketResponseAs[T, ?], meta: ResponseMetadata, ws: WebSocket[Task] ): Task[T] = bodyFromWs(responseAs, ws, meta) diff --git a/effects/zio1/src/main/scalajvm/sttp/client4/httpclient/zio/package.scala b/effects/zio1/src/main/scalajvm/sttp/client4/httpclient/zio/package.scala index 5e4d065c6a..072f29615a 100644 --- a/effects/zio1/src/main/scalajvm/sttp/client4/httpclient/zio/package.scala +++ b/effects/zio1/src/main/scalajvm/sttp/client4/httpclient/zio/package.scala @@ -31,7 +31,7 @@ package object zio { * Known exceptions are converted to one of [[SttpClientException]]. Other exceptions are kept unchanged. */ def send[T]( - request: GenericRequest[T, ZioStreams with Effect[Task] with WebSockets] + request: GenericRequest[T, ZioStreams & Effect[Task] & WebSockets] ): RIO[SttpClient, Response[T]] = ZIO.accessM(env => env.get[SttpClient.Service].send(request)) @@ -39,8 +39,8 @@ package object zio { * websockets or resource-safe streaming) to use an `R` environment. */ def sendR[T, R]( - request: GenericRequest[T, ZioStreams with WebSockets with Effect[RIO[R, *]]] - ): RIO[SttpClient with R, Response[T]] = + request: GenericRequest[T, ZioStreams & WebSockets & Effect[RIO[R, *]]] + ): RIO[SttpClient & R, Response[T]] = ZIO.accessM(env => env.get[SttpClient.Service].extendEnv[R].send(request)) object SttpClientStubbing extends WebSocketStreamClientStubbing[Any, ZioStreams] { @@ -51,14 +51,14 @@ package object zio { object stubbing { import SttpClientStubbing.StubbingWhenRequest - def whenRequestMatches(p: GenericRequest[_, _] => Boolean): StubbingWhenRequest = + def whenRequestMatches(p: GenericRequest[?, ?] => Boolean): StubbingWhenRequest = StubbingWhenRequest(p) val whenAnyRequest: StubbingWhenRequest = StubbingWhenRequest(_ => true) def whenRequestMatchesPartial( - partial: PartialFunction[GenericRequest[_, _], Response[StubBody]] + partial: PartialFunction[GenericRequest[?, ?], Response[StubBody]] ): URIO[SttpClientStubbing, Unit] = ZIO.accessM(_.get.whenRequestMatchesPartial(partial)) } diff --git a/effects/zio1/src/test/scalajs/sttp/client4/impl/zio/FetchZioStreamingTest.scala b/effects/zio1/src/test/scalajs/sttp/client4/impl/zio/FetchZioStreamingTest.scala index 56593c8de7..c78fa0f026 100644 --- a/effects/zio1/src/test/scalajs/sttp/client4/impl/zio/FetchZioStreamingTest.scala +++ b/effects/zio1/src/test/scalajs/sttp/client4/impl/zio/FetchZioStreamingTest.scala @@ -17,7 +17,7 @@ class FetchZioStreamingTest extends StreamingTest[Task, ZioStreams] with ZioTest override implicit val convertToFuture: ConvertToFuture[Task] = convertZioTaskToFuture override def bodyProducer(chunks: Iterable[Array[Byte]]): ZStream[Any, Throwable, Byte] = - ZStream.fromChunks(chunks.map(Chunk.fromArray).toSeq: _*) + ZStream.fromChunks(chunks.map(Chunk.fromArray).toSeq*) override def bodyConsumer(stream: ZStream[Any, Throwable, Byte]): Task[String] = stream.runCollect.map(bytes => new String(bytes.toArray, Utf8)) diff --git a/effects/zio1/src/test/scalajs/sttp/client4/impl/zio/FetchZioWebSocketTest.scala b/effects/zio1/src/test/scalajs/sttp/client4/impl/zio/FetchZioWebSocketTest.scala index dfc0b21fa6..4e7d901a6e 100644 --- a/effects/zio1/src/test/scalajs/sttp/client4/impl/zio/FetchZioWebSocketTest.scala +++ b/effects/zio1/src/test/scalajs/sttp/client4/impl/zio/FetchZioWebSocketTest.scala @@ -26,14 +26,14 @@ class FetchZioWebSocketTest extends WebSocketTest[Task] with WebSocketStreamingT override val streams: ZioStreams = ZioStreams override def prepend(item: WebSocketFrame.Text)( - to: streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] - ): streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] = + to: streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] + ): streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] = to.andThen(rest => ZStream.succeed(item) ++ rest) - override def fromTextPipe(function: String => WebSocketFrame): streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] = + override def fromTextPipe(function: String => WebSocketFrame): streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] = ZioWebSockets.fromTextPipe(function) override def functionToPipe( - f: WebSocketFrame.Data[_] => Option[WebSocketFrame] - ): streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] = in => in.mapConcat(m => f(m).toList) + f: WebSocketFrame.Data[?] => Option[WebSocketFrame] + ): streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] = in => in.mapConcat(m => f(m).toList) } diff --git a/effects/zio1/src/test/scalajvm/sttp/client4/httpclient/zio/HttpClientZioStreamingTest.scala b/effects/zio1/src/test/scalajvm/sttp/client4/httpclient/zio/HttpClientZioStreamingTest.scala index 095b7fcc0d..52d5e86320 100644 --- a/effects/zio1/src/test/scalajvm/sttp/client4/httpclient/zio/HttpClientZioStreamingTest.scala +++ b/effects/zio1/src/test/scalajvm/sttp/client4/httpclient/zio/HttpClientZioStreamingTest.scala @@ -18,7 +18,7 @@ class HttpClientZioStreamingTest extends StreamingTest[Task, ZioStreams] with Zi override implicit val convertToFuture: ConvertToFuture[Task] = convertZioTaskToFuture override def bodyProducer(chunks: Iterable[Array[Byte]]): ZStream[Any, Throwable, Byte] = - Stream.fromChunks(chunks.map(Chunk.fromArray).toSeq: _*) + Stream.fromChunks(chunks.map(Chunk.fromArray).toSeq*) override def bodyConsumer(stream: ZStream[Any, Throwable, Byte]): Task[String] = stream.runCollect.map(bytes => new String(bytes.toArray, Utf8)) diff --git a/effects/zio1/src/test/scalajvm/sttp/client4/httpclient/zio/HttpClientZioWebSocketTest.scala b/effects/zio1/src/test/scalajvm/sttp/client4/httpclient/zio/HttpClientZioWebSocketTest.scala index a301a36e93..8957b16805 100644 --- a/effects/zio1/src/test/scalajvm/sttp/client4/httpclient/zio/HttpClientZioWebSocketTest.scala +++ b/effects/zio1/src/test/scalajvm/sttp/client4/httpclient/zio/HttpClientZioWebSocketTest.scala @@ -22,18 +22,18 @@ class HttpClientZioWebSocketTest override val streams: ZioStreams = ZioStreams override def functionToPipe( - f: WebSocketFrame.Data[_] => Option[WebSocketFrame] - ): ZioStreams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] = + f: WebSocketFrame.Data[?] => Option[WebSocketFrame] + ): ZioStreams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] = in => in.mapConcat(m => f(m).toList) override def fromTextPipe( function: String => WebSocketFrame - ): ZioStreams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] = + ): ZioStreams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] = ZioWebSockets.fromTextPipe[Any](function) override def prepend(item: WebSocketFrame.Text)( - to: PipeR[Any, WebSocketFrame.Data[_], WebSocketFrame] - ): ZioStreams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] = + to: PipeR[Any, WebSocketFrame.Data[?], WebSocketFrame] + ): ZioStreams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] = to.andThen(rest => ZStream(item) ++ rest) override def concurrently[T](fs: List[() => Task[T]]): Task[List[T]] = Task.collectAllPar(fs.map(_())) diff --git a/effects/zio1/src/test/scalajvm/sttp/client4/impl/zio/ZioWebSocketsTest.scala b/effects/zio1/src/test/scalajvm/sttp/client4/impl/zio/ZioWebSocketsTest.scala index 412ab863bd..94e16e1183 100644 --- a/effects/zio1/src/test/scalajvm/sttp/client4/impl/zio/ZioWebSocketsTest.scala +++ b/effects/zio1/src/test/scalajvm/sttp/client4/impl/zio/ZioWebSocketsTest.scala @@ -36,7 +36,7 @@ class ZioWebSocketsTest extends AnyFlatSpec with Matchers with ZioTestBase { } private def sentFrames(incoming: List[WebSocketFrame])( - pipe: ZStream[Any, Throwable, WebSocketFrame.Data[_]] => ZStream[Any, Throwable, WebSocketFrame] + pipe: ZStream[Any, Throwable, WebSocketFrame.Data[?]] => ZStream[Any, Throwable, WebSocketFrame] ): List[(WebSocketFrame, Boolean)] = runtime.unsafeRun(for { incomingRef <- Ref.make(incoming) diff --git a/examples/src/main/scala/sttp/client4/examples/logging/logAsStringBackend.scala b/examples/src/main/scala/sttp/client4/examples/logging/logAsStringBackend.scala index f7f19a5eb0..97e6fe9543 100644 --- a/examples/src/main/scala/sttp/client4/examples/logging/logAsStringBackend.scala +++ b/examples/src/main/scala/sttp/client4/examples/logging/logAsStringBackend.scala @@ -9,7 +9,7 @@ import sttp.client4.* import sttp.client4.wrappers.DelegateBackend class LogAsStringBackendWrapper[F[_], P](delegate: GenericBackend[F, P]) extends DelegateBackend(delegate): - override def send[T](request: GenericRequest[T, P with Effect[F]]): F[Response[T]] = + override def send[T](request: GenericRequest[T, P & Effect[F]]): F[Response[T]] = request match case r: Request[T] @unchecked => request.response match diff --git a/examples/src/main/scala/sttp/client4/examples/observability/metricsWrapperPekkoHttp.scala b/examples/src/main/scala/sttp/client4/examples/observability/metricsWrapperPekkoHttp.scala index ceaba5941c..3a72d7e1b8 100644 --- a/examples/src/main/scala/sttp/client4/examples/observability/metricsWrapperPekkoHttp.scala +++ b/examples/src/main/scala/sttp/client4/examples/observability/metricsWrapperPekkoHttp.scala @@ -34,7 +34,7 @@ val MetricPrefixAttributeKey = AttributeKey[MetricPrefix] abstract class MetricWrapper[P](delegate: GenericBackend[Future, P], metrics: MetricsServer) extends DelegateBackend(delegate): - override def send[T](request: GenericRequest[T, P with Effect[Future]]): Future[Response[T]] = + override def send[T](request: GenericRequest[T, P & Effect[Future]]): Future[Response[T]] = val start = System.currentTimeMillis() def report(metricSuffix: String): Future[Unit] = diff --git a/examples/src/main/scala/sttp/client4/examples/wrapper/addHeaderBackend.scala b/examples/src/main/scala/sttp/client4/examples/wrapper/addHeaderBackend.scala index 5f10498273..7d7a33d77a 100644 --- a/examples/src/main/scala/sttp/client4/examples/wrapper/addHeaderBackend.scala +++ b/examples/src/main/scala/sttp/client4/examples/wrapper/addHeaderBackend.scala @@ -16,7 +16,7 @@ import sttp.model.Header class AddHeaderBackendWrapper[F[_], P](delegate: GenericBackend[F, P], headers: List[Header]) extends DelegateBackend(delegate): - override def send[T](request: GenericRequest[T, P with Effect[F]]): F[Response[T]] = + override def send[T](request: GenericRequest[T, P & Effect[F]]): F[Response[T]] = delegate.send(headers.foldLeft(request) { case (r, h) => r.header(h) }) object AddHeaderBackendWrapper: diff --git a/examples/src/main/scala/sttp/client4/examples/wrapper/retryingBackend.scala b/examples/src/main/scala/sttp/client4/examples/wrapper/retryingBackend.scala index bd282b8c9d..589f2ba240 100644 --- a/examples/src/main/scala/sttp/client4/examples/wrapper/retryingBackend.scala +++ b/examples/src/main/scala/sttp/client4/examples/wrapper/retryingBackend.scala @@ -10,10 +10,10 @@ import sttp.client4.wrappers.DelegateBackend class RetryingBackendWrapper[F[_], P](delegate: GenericBackend[F, P], shouldRetry: RetryWhen, maxRetries: Int) extends DelegateBackend(delegate): - override def send[T](request: GenericRequest[T, P with Effect[F]]): F[Response[T]] = + override def send[T](request: GenericRequest[T, P & Effect[F]]): F[Response[T]] = sendWithRetryCounter(request, 0) - private def sendWithRetryCounter[T](request: GenericRequest[T, P with Effect[F]], retries: Int): F[Response[T]] = + private def sendWithRetryCounter[T](request: GenericRequest[T, P & Effect[F]], retries: Int): F[Response[T]] = val r = monad.handleError(delegate.send(request)): case t if shouldRetry(request, Left(t)) && retries < maxRetries => diff --git a/examples/src/main/scala/sttp/client4/examples/ws/WebSocketStreamFs2.scala b/examples/src/main/scala/sttp/client4/examples/ws/WebSocketStreamFs2.scala index 201df8e788..3619382986 100644 --- a/examples/src/main/scala/sttp/client4/examples/ws/WebSocketStreamFs2.scala +++ b/examples/src/main/scala/sttp/client4/examples/ws/WebSocketStreamFs2.scala @@ -15,7 +15,7 @@ import sttp.client4.ws.stream.* import sttp.ws.WebSocketFrame object WebSocketStreamFs2 extends IOApp: - def webSocketFramePipe: Pipe[IO, WebSocketFrame.Data[_], WebSocketFrame] = { input => + def webSocketFramePipe: Pipe[IO, WebSocketFrame.Data[?], WebSocketFrame] = { input => Stream.emit(WebSocketFrame.text("1")) ++ input.flatMap { case WebSocketFrame.Text("10", _, _) => println("Received 10 messages, sending close frame") diff --git a/http4s-backend/src/main/scala/sttp/client4/http4s/Http4sBackendBase.scala b/http4s-backend/src/main/scala/sttp/client4/http4s/Http4sBackendBase.scala index 6c37dcb3da..52b1f1b2f5 100644 --- a/http4s-backend/src/main/scala/sttp/client4/http4s/Http4sBackendBase.scala +++ b/http4s-backend/src/main/scala/sttp/client4/http4s/Http4sBackendBase.scala @@ -36,7 +36,7 @@ private[http4s] abstract class Http4sBackendBase[F[_]](implicit protected val as protected def customizeRequest: Http4sRequest[F] => Http4sRequest[F] protected def compressionHandlers: CompressionHandlers[Fs2Streams[F], EntityBody[F]] - type R = Fs2Streams[F] with sttp.capabilities.Effect[F] + type R = Fs2Streams[F] & sttp.capabilities.Effect[F] override def send[T](r: GenericRequest[T, R]): F[Response[T]] = adjustExceptions(r) { @@ -151,7 +151,8 @@ private[http4s] abstract class Http4sBackendBase[F[_]](implicit protected val as private def basicBodyToHttp4s(body: BasicBodyPart): http4s.Entity[F] = body match { case StringBody(b, encoding, _) => - http4s.EntityEncoder.stringEncoder(charsetToHttp4s(encoding)).toEntity(b) + implicit val charset: http4s.Charset = charsetToHttp4s(encoding) + http4s.EntityEncoder.stringEncoder.toEntity(b) case ByteArrayBody(b, _) => http4s.EntityEncoder.byteArrayEncoder.toEntity(b) @@ -184,7 +185,7 @@ private[http4s] abstract class Http4sBackendBase[F[_]](implicit protected val as (http4s.EntityEncoder.multipartEncoder.toEntity(multipart), multipart.headers) } - private def multipartToHttp4s(mp: Part[BodyPart[_]]): http4s.multipart.Part[F] = { + private def multipartToHttp4s(mp: Part[BodyPart[?]]): http4s.multipart.Part[F] = { val contentDisposition = http4s.Header.Raw(CIString(HeaderNames.ContentDisposition), mp.contentDispositionHeaderValue) val otherHeaders = mp.headers.map(h => http4s.Header.Raw(CIString(h.name), h.value)) @@ -258,7 +259,7 @@ private[http4s] abstract class Http4sBackendBase[F[_]](implicit protected val as (response.body, () => signalBodyComplete).pure[F] override protected def handleWS[T]( - responseAs: GenericWebSocketResponseAs[T, _], + responseAs: GenericWebSocketResponseAs[T, ?], meta: ResponseMetadata, ws: Nothing ): F[T] = ws @@ -271,10 +272,10 @@ private[http4s] abstract class Http4sBackendBase[F[_]](implicit protected val as override protected def cleanupWhenGotWebSocket(response: Nothing, e: GotAWebSocketException): F[Unit] = response } - private def adjustExceptions[T](r: GenericRequest[_, _])(t: => F[T]): F[T] = + private def adjustExceptions[T](r: GenericRequest[?, ?])(t: => F[T]): F[T] = SttpClientException.adjustExceptions(monad)(t)(http4sExceptionToSttpClientException(r, _)) - private def http4sExceptionToSttpClientException(request: GenericRequest[_, _], e: Exception): Option[Exception] = + private def http4sExceptionToSttpClientException(request: GenericRequest[?, ?], e: Exception): Option[Exception] = e match { case e: org.http4s.client.ConnectionFailure => Some(new SttpClientException.ConnectException(request, e)) case e: org.http4s.InvalidBodyException => Some(new SttpClientException.ReadException(request, e)) diff --git a/http4s-backend/src/main/scalajvm/sttp/client4/http4s/Http4sBackend.scala b/http4s-backend/src/main/scalajvm/sttp/client4/http4s/Http4sBackend.scala index 5adc4f2835..0b25359ddb 100644 --- a/http4s-backend/src/main/scalajvm/sttp/client4/http4s/Http4sBackend.scala +++ b/http4s-backend/src/main/scalajvm/sttp/client4/http4s/Http4sBackend.scala @@ -22,11 +22,16 @@ object Http4sBackend { def defaultCompressionHandlers[F[_]: Async]: CompressionHandlers[Fs2Streams[F], Stream[F, Byte]] = Http4sBackendBase.defaultCompressionHandlers[F] + private def defaultCompressionHandlersFor[F[_]](F: Async[F]): CompressionHandlers[Fs2Streams[F], Stream[F, Byte]] = { + implicit val ev: Async[F] = F + defaultCompressionHandlers[F] + } + def usingClient[F[_]: Async]( client: Client[F], - customizeRequest: Http4sRequest[F] => Http4sRequest[F] = identity[Http4sRequest[F]] _ + customizeRequest: Http4sRequest[F] => Http4sRequest[F] = identity[Http4sRequest[F]](_) ): StreamBackend[F, Fs2Streams[F]] = - Http4sBackendBase.usingClient(client, customizeRequest, defaultCompressionHandlers[F](_: Async[F])) + Http4sBackendBase.usingClient(client, customizeRequest, defaultCompressionHandlersFor[F](_)) def usingClient[F[_]: Async]( client: Client[F], @@ -37,9 +42,9 @@ object Http4sBackend { def usingBlazeClientBuilder[F[_]: Async]( blazeClientBuilder: BlazeClientBuilder[F], - customizeRequest: Http4sRequest[F] => Http4sRequest[F] = identity[Http4sRequest[F]] _ + customizeRequest: Http4sRequest[F] => Http4sRequest[F] = identity[Http4sRequest[F]](_) ): Resource[F, StreamBackend[F, Fs2Streams[F]]] = - usingBlazeClientBuilder(blazeClientBuilder, customizeRequest, defaultCompressionHandlers[F](_: Async[F])) + usingBlazeClientBuilder(blazeClientBuilder, customizeRequest, defaultCompressionHandlersFor[F](_)) def usingBlazeClientBuilder[F[_]: Async]( blazeClientBuilder: BlazeClientBuilder[F], @@ -49,17 +54,17 @@ object Http4sBackend { blazeClientBuilder.resource.map(c => usingClient(c, customizeRequest, compressionHandlers)) def usingDefaultBlazeClientBuilder[F[_]: Async]( - customizeRequest: Http4sRequest[F] => Http4sRequest[F] = identity[Http4sRequest[F]] _, + customizeRequest: Http4sRequest[F] => Http4sRequest[F] = identity[Http4sRequest[F]](_), compressionHandlers: Async[F] => CompressionHandlers[Fs2Streams[F], EntityBody[F]] = - defaultCompressionHandlers[F](_: Async[F]) + defaultCompressionHandlersFor[F](_) ): Resource[F, StreamBackend[F, Fs2Streams[F]]] = usingBlazeClientBuilder(BlazeClientBuilder[F], customizeRequest, compressionHandlers) def usingEmberClientBuilder[F[_]: Async]( emberClientBuilder: EmberClientBuilder[F], - customizeRequest: Http4sRequest[F] => Http4sRequest[F] = identity[Http4sRequest[F]] _ + customizeRequest: Http4sRequest[F] => Http4sRequest[F] = identity[Http4sRequest[F]](_) ): Resource[F, StreamBackend[F, Fs2Streams[F]]] = - usingEmberClientBuilder(emberClientBuilder, customizeRequest, defaultCompressionHandlers[F](_: Async[F])) + usingEmberClientBuilder(emberClientBuilder, customizeRequest, defaultCompressionHandlersFor[F](_)) def usingEmberClientBuilder[F[_]: Async]( emberClientBuilder: EmberClientBuilder[F], @@ -69,9 +74,9 @@ object Http4sBackend { emberClientBuilder.build.map(c => usingClient(c, customizeRequest, compressionHandlers)) def usingDefaultEmberClientBuilder[F[_]: Async]( - customizeRequest: Http4sRequest[F] => Http4sRequest[F] = identity[Http4sRequest[F]] _, + customizeRequest: Http4sRequest[F] => Http4sRequest[F] = identity[Http4sRequest[F]](_), compressionHandlers: Async[F] => CompressionHandlers[Fs2Streams[F], EntityBody[F]] = - defaultCompressionHandlers[F](_: Async[F]) + defaultCompressionHandlersFor[F](_) ): Resource[F, StreamBackend[F, Fs2Streams[F]]] = usingEmberClientBuilder(EmberClientBuilder.default[F], customizeRequest, compressionHandlers) diff --git a/http4s-backend/src/main/scalanative/sttp/client4/http4s/Http4sBackend.scala b/http4s-backend/src/main/scalanative/sttp/client4/http4s/Http4sBackend.scala index 8b06186f97..7a95081d4c 100644 --- a/http4s-backend/src/main/scalanative/sttp/client4/http4s/Http4sBackend.scala +++ b/http4s-backend/src/main/scalanative/sttp/client4/http4s/Http4sBackend.scala @@ -22,11 +22,16 @@ object Http4sBackend { def defaultCompressionHandlers[F[_]: Async]: CompressionHandlers[Fs2Streams[F], Stream[F, Byte]] = Http4sBackendBase.defaultCompressionHandlers[F] + private def defaultCompressionHandlersFor[F[_]](F: Async[F]): CompressionHandlers[Fs2Streams[F], Stream[F, Byte]] = { + implicit val ev: Async[F] = F + defaultCompressionHandlers[F] + } + def usingClient[F[_]: Async]( client: Client[F], - customizeRequest: Http4sRequest[F] => Http4sRequest[F] = identity[Http4sRequest[F]] _ + customizeRequest: Http4sRequest[F] => Http4sRequest[F] = identity[Http4sRequest[F]](_) ): StreamBackend[F, Fs2Streams[F]] = - Http4sBackendBase.usingClient(client, customizeRequest, defaultCompressionHandlers[F](_: Async[F])) + Http4sBackendBase.usingClient(client, customizeRequest, defaultCompressionHandlersFor[F](_)) def usingClient[F[_]: Async]( client: Client[F], @@ -37,9 +42,9 @@ object Http4sBackend { def usingEmberClientBuilder[F[_]: Async: Network]( emberClientBuilder: EmberClientBuilder[F], - customizeRequest: Http4sRequest[F] => Http4sRequest[F] = identity[Http4sRequest[F]] _ + customizeRequest: Http4sRequest[F] => Http4sRequest[F] = identity[Http4sRequest[F]](_) ): Resource[F, StreamBackend[F, Fs2Streams[F]]] = - usingEmberClientBuilder(emberClientBuilder, customizeRequest, defaultCompressionHandlers[F](_: Async[F])) + usingEmberClientBuilder(emberClientBuilder, customizeRequest, defaultCompressionHandlersFor[F](_)) def usingEmberClientBuilder[F[_]: Async: Network]( emberClientBuilder: EmberClientBuilder[F], @@ -49,9 +54,9 @@ object Http4sBackend { emberClientBuilder.build.map(c => usingClient(c, customizeRequest, compressionHandlers)) def usingDefaultEmberClientBuilder[F[_]: Async: Network]( - customizeRequest: Http4sRequest[F] => Http4sRequest[F] = identity[Http4sRequest[F]] _, + customizeRequest: Http4sRequest[F] => Http4sRequest[F] = identity[Http4sRequest[F]](_), compressionHandlers: Async[F] => CompressionHandlers[Fs2Streams[F], EntityBody[F]] = - defaultCompressionHandlers[F](_: Async[F]) + defaultCompressionHandlersFor[F](_) ): Resource[F, StreamBackend[F, Fs2Streams[F]]] = usingEmberClientBuilder(EmberClientBuilder.default[F], customizeRequest, compressionHandlers) diff --git a/http4s-ce2-backend/src/main/scala/sttp/client4/http4s/Http4sBackend.scala b/http4s-ce2-backend/src/main/scala/sttp/client4/http4s/Http4sBackend.scala index 7c11496185..d6ba157b51 100644 --- a/http4s-ce2-backend/src/main/scala/sttp/client4/http4s/Http4sBackend.scala +++ b/http4s-ce2-backend/src/main/scala/sttp/client4/http4s/Http4sBackend.scala @@ -37,7 +37,7 @@ class Http4sBackend[F[_]: ConcurrentEffect: ContextShift]( customizeRequest: Http4sRequest[F] => Http4sRequest[F], compressionHandlers: CompressionHandlers[Fs2Streams[F], EntityBody[F]] ) extends StreamBackend[F, Fs2Streams[F]] { - type R = Fs2Streams[F] with sttp.capabilities.Effect[F] + type R = Fs2Streams[F] & sttp.capabilities.Effect[F] override def send[T](r: GenericRequest[T, R]): F[Response[T]] = adjustExceptions(r) { @@ -146,7 +146,8 @@ class Http4sBackend[F[_]: ConcurrentEffect: ContextShift]( private def basicBodyToHttp4s(body: BasicBodyPart): http4s.Entity[F] = body match { case StringBody(b, encoding, _) => - http4s.EntityEncoder.stringEncoder(charsetToHttp4s(encoding)).toEntity(b) + implicit val charset: http4s.Charset = charsetToHttp4s(encoding) + http4s.EntityEncoder.stringEncoder.toEntity(b) case ByteArrayBody(b, _) => http4s.EntityEncoder.byteArrayEncoder.toEntity(b) @@ -179,7 +180,7 @@ class Http4sBackend[F[_]: ConcurrentEffect: ContextShift]( (http4s.EntityEncoder.multipartEncoder.toEntity(multipart), multipart.headers) } - private def multipartToHttp4s(mp: Part[BodyPart[_]]): http4s.multipart.Part[F] = { + private def multipartToHttp4s(mp: Part[BodyPart[?]]): http4s.multipart.Part[F] = { val contentDisposition = http4s.Header.Raw(CIString(HeaderNames.ContentDisposition), mp.contentDispositionHeaderValue) val otherHeaders = mp.headers.map(h => http4s.Header.Raw(CIString(h.name), h.value)) @@ -253,7 +254,7 @@ class Http4sBackend[F[_]: ConcurrentEffect: ContextShift]( (response.body, () => signalBodyComplete).pure[F] override protected def handleWS[T]( - responseAs: GenericWebSocketResponseAs[T, _], + responseAs: GenericWebSocketResponseAs[T, ?], meta: ResponseMetadata, ws: Nothing ): F[T] = ws @@ -266,10 +267,10 @@ class Http4sBackend[F[_]: ConcurrentEffect: ContextShift]( override protected def cleanupWhenGotWebSocket(response: Nothing, e: GotAWebSocketException): F[Unit] = response } - private def adjustExceptions[T](r: GenericRequest[_, _])(t: => F[T]): F[T] = + private def adjustExceptions[T](r: GenericRequest[?, ?])(t: => F[T]): F[T] = SttpClientException.adjustExceptions(monad)(t)(http4sExceptionToSttpClientException(r, _)) - private def http4sExceptionToSttpClientException(request: GenericRequest[_, _], e: Exception): Option[Exception] = + private def http4sExceptionToSttpClientException(request: GenericRequest[?, ?], e: Exception): Option[Exception] = e match { case e: org.http4s.client.ConnectionFailure => Some(new SttpClientException.ConnectException(request, e)) case e: org.http4s.InvalidBodyException => Some(new SttpClientException.ReadException(request, e)) @@ -308,30 +309,35 @@ object Http4sBackend { List(new GZipFs2Decompressor, new DeflateFs2Decompressor) ) + private def defaultCompressionHandlersFor[F[_]](F: Sync[F]): CompressionHandlers[Fs2Streams[F], Stream[F, Byte]] = { + implicit val ev: Sync[F] = F + defaultCompressionHandlers[F] + } + def usingClient[F[_]: ConcurrentEffect: ContextShift]( client: Client[F], blocker: Blocker, - customizeRequest: Http4sRequest[F] => Http4sRequest[F] = identity[Http4sRequest[F]] _, + customizeRequest: Http4sRequest[F] => Http4sRequest[F] = identity[Http4sRequest[F]](_), compressionHandlers: Sync[F] => CompressionHandlers[Fs2Streams[F], EntityBody[F]] = - defaultCompressionHandlers[F](_: Sync[F]) + defaultCompressionHandlersFor[F](_) ): StreamBackend[F, Fs2Streams[F]] = FollowRedirectsBackend(new Http4sBackend[F](client, blocker, customizeRequest, compressionHandlers(implicitly))) def usingBlazeClientBuilder[F[_]: ConcurrentEffect: ContextShift]( blazeClientBuilder: BlazeClientBuilder[F], blocker: Blocker, - customizeRequest: Http4sRequest[F] => Http4sRequest[F] = identity[Http4sRequest[F]] _, + customizeRequest: Http4sRequest[F] => Http4sRequest[F] = identity[Http4sRequest[F]](_), compressionHandlers: Sync[F] => CompressionHandlers[Fs2Streams[F], EntityBody[F]] = - defaultCompressionHandlers[F](_: Sync[F]) + defaultCompressionHandlersFor[F](_) ): Resource[F, StreamBackend[F, Fs2Streams[F]]] = blazeClientBuilder.resource.map(c => usingClient(c, blocker, customizeRequest, compressionHandlers)) def usingDefaultBlazeClientBuilder[F[_]: ConcurrentEffect: ContextShift]( blocker: Blocker, clientExecutionContext: ExecutionContext = ExecutionContext.global, - customizeRequest: Http4sRequest[F] => Http4sRequest[F] = identity[Http4sRequest[F]] _, + customizeRequest: Http4sRequest[F] => Http4sRequest[F] = identity[Http4sRequest[F]](_), compressionHandlers: Sync[F] => CompressionHandlers[Fs2Streams[F], EntityBody[F]] = - defaultCompressionHandlers[F](_: Sync[F]) + defaultCompressionHandlersFor[F](_) ): Resource[F, StreamBackend[F, Fs2Streams[F]]] = usingBlazeClientBuilder( BlazeClientBuilder[F](clientExecutionContext), diff --git a/json/common/src/main/scala/sttp/client4/IsOption.scala b/json/common/src/main/scala/sttp/client4/IsOption.scala index ae91dbad00..7dde2ea092 100644 --- a/json/common/src/main/scala/sttp/client4/IsOption.scala +++ b/json/common/src/main/scala/sttp/client4/IsOption.scala @@ -14,7 +14,7 @@ object IsOption { } implicit def optionIsOption[T]: IsOption[Option[T]] = True - implicit def leftOptionIsOption[T]: IsOption[Either[Option[T], _]] = True - implicit def rightOptionIsOption[T]: IsOption[Either[_, Option[T]]] = True + implicit def leftOptionIsOption[T]: IsOption[Either[Option[T], ?]] = True + implicit def rightOptionIsOption[T]: IsOption[Either[?, Option[T]]] = True implicit def otherIsNotOption[T]: IsOption[T] = False } diff --git a/json/zio-json/src/main/scalajvm/sttp/client4/ziojson/SttpZioJsonApiExtensions.scala b/json/zio-json/src/main/scalajvm/sttp/client4/ziojson/SttpZioJsonApiExtensions.scala index 6a346be3ca..01e110dadc 100644 --- a/json/zio-json/src/main/scalajvm/sttp/client4/ziojson/SttpZioJsonApiExtensions.scala +++ b/json/zio-json/src/main/scalajvm/sttp/client4/ziojson/SttpZioJsonApiExtensions.scala @@ -13,8 +13,7 @@ import sttp.client4.ResponseException.UnexpectedStatusCode import sttp.client4.ResponseException.DeserializationException trait SttpZioJsonApiExtensions { this: SttpZioJsonApi => - def asJsonStream[B: JsonDecoder] - : StreamResponseAs[Either[ResponseException[String], B], ZioStreams with Effect[Task]] = + def asJsonStream[B: JsonDecoder]: StreamResponseAs[Either[ResponseException[String], B], ZioStreams & Effect[Task]] = asStreamWithMetadata(ZioStreams)((s, meta) => JsonDecoder[B] .decodeJsonStream(ZPipeline.utf8Decode.apply(s).mapChunks(_.flatMap(_.toCharArray))) diff --git a/json/zio1-json/src/main/scalajvm/sttp/client4/ziojson/SttpZioJsonApiExtensions.scala b/json/zio1-json/src/main/scalajvm/sttp/client4/ziojson/SttpZioJsonApiExtensions.scala index b63a038386..5d1eed9d19 100644 --- a/json/zio1-json/src/main/scalajvm/sttp/client4/ziojson/SttpZioJsonApiExtensions.scala +++ b/json/zio1-json/src/main/scalajvm/sttp/client4/ziojson/SttpZioJsonApiExtensions.scala @@ -15,7 +15,7 @@ import sttp.client4.ResponseException.UnexpectedStatusCode trait SttpZioJsonApiExtensions { this: SttpZioJsonApi => def asJsonStream[B: JsonDecoder] - : StreamResponseAs[Either[ResponseException[String], B], ZioStreams with Effect[RIO[Blocking, *]]] = + : StreamResponseAs[Either[ResponseException[String], B], ZioStreams & Effect[RIO[Blocking, *]]] = asStreamWithMetadata(ZioStreams)((s, meta) => JsonDecoder[B] .decodeJsonStream(s >>> ZTransducer.utf8Decode.mapChunks(_.flatMap(_.toCharArray))) diff --git a/observability/opentelemetry-backend/src/main/scala/sttp/client4/opentelemetry/OpenTelemetryDefaults.scala b/observability/opentelemetry-backend/src/main/scala/sttp/client4/opentelemetry/OpenTelemetryDefaults.scala index 30c87149ff..9a51018e57 100644 --- a/observability/opentelemetry-backend/src/main/scala/sttp/client4/opentelemetry/OpenTelemetryDefaults.scala +++ b/observability/opentelemetry-backend/src/main/scala/sttp/client4/opentelemetry/OpenTelemetryDefaults.scala @@ -12,26 +12,26 @@ import sttp.model.ResponseMetadata object OpenTelemetryDefaults { /** @see https://opentelemetry.io/docs/specs/semconv/http/http-spans/#name */ - def spanName(request: GenericRequest[_, _]): String = s"${request.method.method}" + def spanName(request: GenericRequest[?, ?]): String = s"${request.method.method}" /** @see https://opentelemetry.io/docs/specs/semconv/http/http-metrics/#http-client */ - def requestAttributes(request: GenericRequest[_, _]): Attributes = requestAttributesBuilder(request).build() + def requestAttributes(request: GenericRequest[?, ?]): Attributes = requestAttributesBuilder(request).build() /** @see * https://opentelemetry.io/docs/specs/semconv/http/http-spans/#http-client (full url is required for tracing, but * not for metrics) */ - def requestAttributesWithFullUrl(request: GenericRequest[_, _]): Attributes = + def requestAttributesWithFullUrl(request: GenericRequest[?, ?]): Attributes = requestAttributesBuilder(request).put(UrlAttributes.URL_FULL, request.uri.toString()).build() - private def requestAttributesBuilder(request: GenericRequest[_, _]): AttributesBuilder = + private def requestAttributesBuilder(request: GenericRequest[?, ?]): AttributesBuilder = Attributes.builder .put(HttpAttributes.HTTP_REQUEST_METHOD, request.method.method) .put(ServerAttributes.SERVER_ADDRESS, request.uri.host.getOrElse("unknown")) .put(ServerAttributes.SERVER_PORT, request.uri.port.getOrElse(80)) /** @see https://opentelemetry.io/docs/specs/semconv/http/http-metrics/#http-client */ - def responseAttributes(request: GenericRequest[_, _], response: ResponseMetadata): Attributes = + def responseAttributes(request: GenericRequest[?, ?], response: ResponseMetadata): Attributes = Attributes.builder .put(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, response.code.code.toLong: java.lang.Long) .build() diff --git a/observability/opentelemetry-backend/src/main/scala/sttp/client4/opentelemetry/OpenTelemetryMetricsBackend.scala b/observability/opentelemetry-backend/src/main/scala/sttp/client4/opentelemetry/OpenTelemetryMetricsBackend.scala index c37b739b30..322b8b7d3f 100644 --- a/observability/opentelemetry-backend/src/main/scala/sttp/client4/opentelemetry/OpenTelemetryMetricsBackend.scala +++ b/observability/opentelemetry-backend/src/main/scala/sttp/client4/opentelemetry/OpenTelemetryMetricsBackend.scala @@ -93,7 +93,7 @@ private class OpenTelemetryMetricsListener(config: OpenTelemetryMetricsConfig) private val histograms = new ConcurrentHashMap[String, DoubleHistogram]() private val upAndDownCounter = new ConcurrentHashMap[String, LongUpDownCounter]() - override def before(request: GenericRequest[_, _]): Option[Long] = { + override def before(request: GenericRequest[?, ?]): Option[Long] = { val attributes = config.requestAttributes(request) updateInProgressCounter(request, 1, attributes) @@ -102,16 +102,16 @@ private class OpenTelemetryMetricsListener(config: OpenTelemetryMetricsConfig) } override def responseBodyReceived( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], response: ResponseMetadata, tag: Option[Long] ): Unit = captureResponseMetrics(request, response, tag) override def responseHandled( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], response: ResponseMetadata, tag: Option[Long], - e: Option[ResponseException[_]] + e: Option[ResponseException[?]] ): Unit = { // responseBodyReceived is not called for WebSocket requests // ignoring the tag as there's no point in capturing timing information for WebSockets @@ -119,7 +119,7 @@ private class OpenTelemetryMetricsListener(config: OpenTelemetryMetricsConfig) } private def captureResponseMetrics( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], response: ResponseMetadata, tag: Option[Long] ): Unit = { @@ -144,7 +144,7 @@ private class OpenTelemetryMetricsListener(config: OpenTelemetryMetricsConfig) } override def exception( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], tag: Option[Long], e: Throwable, responseBodyReceivedCalled: Boolean diff --git a/observability/opentelemetry-backend/src/main/scala/sttp/client4/opentelemetry/OpenTelemetryMetricsConfig.scala b/observability/opentelemetry-backend/src/main/scala/sttp/client4/opentelemetry/OpenTelemetryMetricsConfig.scala index 7387b29c93..12f33d1025 100644 --- a/observability/opentelemetry-backend/src/main/scala/sttp/client4/opentelemetry/OpenTelemetryMetricsConfig.scala +++ b/observability/opentelemetry-backend/src/main/scala/sttp/client4/opentelemetry/OpenTelemetryMetricsConfig.scala @@ -12,15 +12,15 @@ import sttp.model.ResponseMetadata final case class OpenTelemetryMetricsConfig( meter: Meter, clock: Clock, - requestToLatencyHistogramMapper: GenericRequest[_, _] => Option[HistogramCollectorConfig], - requestToInProgressCounterMapper: GenericRequest[_, _] => Option[CollectorConfig], - responseToSuccessCounterMapper: (GenericRequest[_, _], ResponseMetadata) => Option[CollectorConfig], - requestToErrorCounterMapper: (GenericRequest[_, _], ResponseMetadata) => Option[CollectorConfig], - requestToFailureCounterMapper: (GenericRequest[_, _], Throwable) => Option[CollectorConfig], - requestToSizeHistogramMapper: GenericRequest[_, _] => Option[HistogramCollectorConfig], - responseToSizeHistogramMapper: (GenericRequest[_, _], ResponseMetadata) => Option[HistogramCollectorConfig], - requestAttributes: GenericRequest[_, _] => Attributes, - responseAttributes: (GenericRequest[_, _], ResponseMetadata) => Attributes, + requestToLatencyHistogramMapper: GenericRequest[?, ?] => Option[HistogramCollectorConfig], + requestToInProgressCounterMapper: GenericRequest[?, ?] => Option[CollectorConfig], + responseToSuccessCounterMapper: (GenericRequest[?, ?], ResponseMetadata) => Option[CollectorConfig], + requestToErrorCounterMapper: (GenericRequest[?, ?], ResponseMetadata) => Option[CollectorConfig], + requestToFailureCounterMapper: (GenericRequest[?, ?], Throwable) => Option[CollectorConfig], + requestToSizeHistogramMapper: GenericRequest[?, ?] => Option[HistogramCollectorConfig], + responseToSizeHistogramMapper: (GenericRequest[?, ?], ResponseMetadata) => Option[HistogramCollectorConfig], + requestAttributes: GenericRequest[?, ?] => Attributes, + responseAttributes: (GenericRequest[?, ?], ResponseMetadata) => Attributes, errorAttributes: Throwable => Attributes ) @@ -28,8 +28,8 @@ object OpenTelemetryMetricsConfig { def apply( openTelemetry: OpenTelemetry, clock: Clock = Clock.systemUTC(), - requestToLatencyHistogramMapper: GenericRequest[_, _] => Option[HistogramCollectorConfig] = - (_: GenericRequest[_, _]) => + requestToLatencyHistogramMapper: GenericRequest[?, ?] => Option[HistogramCollectorConfig] = + (_: GenericRequest[?, ?]) => Some( HistogramCollectorConfig( DefaultLatencyHistogramName, @@ -37,16 +37,16 @@ object OpenTelemetryMetricsConfig { unit = HistogramCollectorConfig.Milliseconds ) ), - requestToInProgressCounterMapper: GenericRequest[_, _] => Option[CollectorConfig] = (_: GenericRequest[_, _]) => + requestToInProgressCounterMapper: GenericRequest[?, ?] => Option[CollectorConfig] = (_: GenericRequest[?, ?]) => Some(CollectorConfig(DefaultRequestsActiveCounterName)), - responseToSuccessCounterMapper: (GenericRequest[_, _], ResponseMetadata) => Option[CollectorConfig] = - (_: GenericRequest[_, _], _: ResponseMetadata) => Some(CollectorConfig(DefaultSuccessCounterName)), - responseToErrorCounterMapper: (GenericRequest[_, _], ResponseMetadata) => Option[CollectorConfig] = - (_: GenericRequest[_, _], _: ResponseMetadata) => Some(CollectorConfig(DefaultErrorCounterName)), - requestToFailureCounterMapper: (GenericRequest[_, _], Throwable) => Option[CollectorConfig] = - (_: GenericRequest[_, _], _: Throwable) => Some(CollectorConfig(DefaultFailureCounterName)), - requestToSizeHistogramMapper: GenericRequest[_, _] => Option[HistogramCollectorConfig] = - (_: GenericRequest[_, _]) => + responseToSuccessCounterMapper: (GenericRequest[?, ?], ResponseMetadata) => Option[CollectorConfig] = + (_: GenericRequest[?, ?], _: ResponseMetadata) => Some(CollectorConfig(DefaultSuccessCounterName)), + responseToErrorCounterMapper: (GenericRequest[?, ?], ResponseMetadata) => Option[CollectorConfig] = + (_: GenericRequest[?, ?], _: ResponseMetadata) => Some(CollectorConfig(DefaultErrorCounterName)), + requestToFailureCounterMapper: (GenericRequest[?, ?], Throwable) => Option[CollectorConfig] = + (_: GenericRequest[?, ?], _: Throwable) => Some(CollectorConfig(DefaultFailureCounterName)), + requestToSizeHistogramMapper: GenericRequest[?, ?] => Option[HistogramCollectorConfig] = + (_: GenericRequest[?, ?]) => Some( HistogramCollectorConfig( DefaultRequestSizeHistogramName, @@ -54,8 +54,8 @@ object OpenTelemetryMetricsConfig { unit = HistogramCollectorConfig.Bytes ) ), - responseToSizeHistogramMapper: (GenericRequest[_, _], ResponseMetadata) => Option[HistogramCollectorConfig] = - (_: GenericRequest[_, _], _: ResponseMetadata) => + responseToSizeHistogramMapper: (GenericRequest[?, ?], ResponseMetadata) => Option[HistogramCollectorConfig] = + (_: GenericRequest[?, ?], _: ResponseMetadata) => Some( HistogramCollectorConfig( DefaultResponseSizeHistogramName, @@ -63,11 +63,11 @@ object OpenTelemetryMetricsConfig { unit = HistogramCollectorConfig.Bytes ) ), - spanName: GenericRequest[_, _] => String = OpenTelemetryDefaults.spanName _, - requestAttributes: GenericRequest[_, _] => Attributes = OpenTelemetryDefaults.requestAttributes _, - responseAttributes: (GenericRequest[_, _], ResponseMetadata) => Attributes = - OpenTelemetryDefaults.responseAttributes _, - errorAttributes: Throwable => Attributes = OpenTelemetryDefaults.errorAttributes _ + spanName: GenericRequest[?, ?] => String = OpenTelemetryDefaults.spanName, + requestAttributes: GenericRequest[?, ?] => Attributes = OpenTelemetryDefaults.requestAttributes, + responseAttributes: (GenericRequest[?, ?], ResponseMetadata) => Attributes = + OpenTelemetryDefaults.responseAttributes, + errorAttributes: Throwable => Attributes = OpenTelemetryDefaults.errorAttributes ): OpenTelemetryMetricsConfig = usingMeter( openTelemetry .meterBuilder(OpenTelemetryDefaults.instrumentationScopeName) @@ -89,8 +89,8 @@ object OpenTelemetryMetricsConfig { def usingMeter( meter: Meter, clock: Clock = Clock.systemUTC(), - requestToLatencyHistogramMapper: GenericRequest[_, _] => Option[HistogramCollectorConfig] = - (_: GenericRequest[_, _]) => + requestToLatencyHistogramMapper: GenericRequest[?, ?] => Option[HistogramCollectorConfig] = + (_: GenericRequest[?, ?]) => Some( HistogramCollectorConfig( DefaultLatencyHistogramName, @@ -98,16 +98,16 @@ object OpenTelemetryMetricsConfig { unit = HistogramCollectorConfig.Milliseconds ) ), - requestToInProgressCounterMapper: GenericRequest[_, _] => Option[CollectorConfig] = (_: GenericRequest[_, _]) => + requestToInProgressCounterMapper: GenericRequest[?, ?] => Option[CollectorConfig] = (_: GenericRequest[?, ?]) => Some(CollectorConfig(DefaultRequestsActiveCounterName)), - responseToSuccessCounterMapper: (GenericRequest[_, _], ResponseMetadata) => Option[CollectorConfig] = - (_: GenericRequest[_, _], _: ResponseMetadata) => Some(CollectorConfig(DefaultSuccessCounterName)), - responseToErrorCounterMapper: (GenericRequest[_, _], ResponseMetadata) => Option[CollectorConfig] = - (_: GenericRequest[_, _], _: ResponseMetadata) => Some(CollectorConfig(DefaultErrorCounterName)), - requestToFailureCounterMapper: (GenericRequest[_, _], Throwable) => Option[CollectorConfig] = - (_: GenericRequest[_, _], _: Throwable) => Some(CollectorConfig(DefaultFailureCounterName)), - requestToSizeHistogramMapper: GenericRequest[_, _] => Option[HistogramCollectorConfig] = - (_: GenericRequest[_, _]) => + responseToSuccessCounterMapper: (GenericRequest[?, ?], ResponseMetadata) => Option[CollectorConfig] = + (_: GenericRequest[?, ?], _: ResponseMetadata) => Some(CollectorConfig(DefaultSuccessCounterName)), + responseToErrorCounterMapper: (GenericRequest[?, ?], ResponseMetadata) => Option[CollectorConfig] = + (_: GenericRequest[?, ?], _: ResponseMetadata) => Some(CollectorConfig(DefaultErrorCounterName)), + requestToFailureCounterMapper: (GenericRequest[?, ?], Throwable) => Option[CollectorConfig] = + (_: GenericRequest[?, ?], _: Throwable) => Some(CollectorConfig(DefaultFailureCounterName)), + requestToSizeHistogramMapper: GenericRequest[?, ?] => Option[HistogramCollectorConfig] = + (_: GenericRequest[?, ?]) => Some( HistogramCollectorConfig( DefaultRequestSizeHistogramName, @@ -115,8 +115,8 @@ object OpenTelemetryMetricsConfig { unit = HistogramCollectorConfig.Bytes ) ), - responseToSizeHistogramMapper: (GenericRequest[_, _], ResponseMetadata) => Option[HistogramCollectorConfig] = - (_: GenericRequest[_, _], _: ResponseMetadata) => + responseToSizeHistogramMapper: (GenericRequest[?, ?], ResponseMetadata) => Option[HistogramCollectorConfig] = + (_: GenericRequest[?, ?], _: ResponseMetadata) => Some( HistogramCollectorConfig( DefaultResponseSizeHistogramName, @@ -124,10 +124,10 @@ object OpenTelemetryMetricsConfig { unit = HistogramCollectorConfig.Bytes ) ), - requestAttributes: GenericRequest[_, _] => Attributes = OpenTelemetryDefaults.requestAttributes _, - responseAttributes: (GenericRequest[_, _], ResponseMetadata) => Attributes = - OpenTelemetryDefaults.responseAttributes _, - errorAttributes: Throwable => Attributes = OpenTelemetryDefaults.errorAttributes _ + requestAttributes: GenericRequest[?, ?] => Attributes = OpenTelemetryDefaults.requestAttributes, + responseAttributes: (GenericRequest[?, ?], ResponseMetadata) => Attributes = + OpenTelemetryDefaults.responseAttributes, + errorAttributes: Throwable => Attributes = OpenTelemetryDefaults.errorAttributes ): OpenTelemetryMetricsConfig = OpenTelemetryMetricsConfig( meter, diff --git a/observability/opentelemetry-backend/src/main/scala/sttp/client4/opentelemetry/OpenTelemetryTracingBackend.scala b/observability/opentelemetry-backend/src/main/scala/sttp/client4/opentelemetry/OpenTelemetryTracingBackend.scala index 3308790678..0748c3d449 100644 --- a/observability/opentelemetry-backend/src/main/scala/sttp/client4/opentelemetry/OpenTelemetryTracingBackend.scala +++ b/observability/opentelemetry-backend/src/main/scala/sttp/client4/opentelemetry/OpenTelemetryTracingBackend.scala @@ -48,7 +48,7 @@ class OpenTelemetryTracingBackend[F[_], P](delegate: GenericBackend[F, P], confi } } - override def send[T](request: GenericRequest[T, P with Effect[F]]): F[Response[T]] = { + override def send[T](request: GenericRequest[T, P & Effect[F]]): F[Response[T]] = { monad .eval { config.tracer diff --git a/observability/opentelemetry-backend/src/main/scala/sttp/client4/opentelemetry/OpenTelemetryTracingConfig.scala b/observability/opentelemetry-backend/src/main/scala/sttp/client4/opentelemetry/OpenTelemetryTracingConfig.scala index a5e741829a..179277321d 100644 --- a/observability/opentelemetry-backend/src/main/scala/sttp/client4/opentelemetry/OpenTelemetryTracingConfig.scala +++ b/observability/opentelemetry-backend/src/main/scala/sttp/client4/opentelemetry/OpenTelemetryTracingConfig.scala @@ -12,9 +12,9 @@ case class OpenTelemetryTracingConfig( tracer: Tracer, propagators: ContextPropagators, clock: Clock, - spanName: GenericRequest[_, _] => String, - requestAttributes: GenericRequest[_, _] => Attributes, - responseAttributes: (GenericRequest[_, _], Response[_]) => Attributes, + spanName: GenericRequest[?, ?] => String, + requestAttributes: GenericRequest[?, ?] => Attributes, + responseAttributes: (GenericRequest[?, ?], Response[?]) => Attributes, errorAttributes: Throwable => Attributes ) @@ -22,11 +22,10 @@ object OpenTelemetryTracingConfig { def apply( openTelemetry: OpenTelemetry, clock: Clock = Clock.systemUTC(), - spanName: GenericRequest[_, _] => String = OpenTelemetryDefaults.spanName _, - requestAttributes: GenericRequest[_, _] => Attributes = OpenTelemetryDefaults.requestAttributesWithFullUrl _, - responseAttributes: (GenericRequest[_, _], Response[_]) => Attributes = - OpenTelemetryDefaults.responseAttributes _, - errorAttributes: Throwable => Attributes = OpenTelemetryDefaults.errorAttributes _ + spanName: GenericRequest[?, ?] => String = OpenTelemetryDefaults.spanName, + requestAttributes: GenericRequest[?, ?] => Attributes = OpenTelemetryDefaults.requestAttributesWithFullUrl, + responseAttributes: (GenericRequest[?, ?], Response[?]) => Attributes = OpenTelemetryDefaults.responseAttributes, + errorAttributes: Throwable => Attributes = OpenTelemetryDefaults.errorAttributes ): OpenTelemetryTracingConfig = usingTracer( openTelemetry .tracerBuilder(OpenTelemetryDefaults.instrumentationScopeName) @@ -44,11 +43,10 @@ object OpenTelemetryTracingConfig { tracer: Tracer, propagators: ContextPropagators, clock: Clock = Clock.systemUTC(), - spanName: GenericRequest[_, _] => String = OpenTelemetryDefaults.spanName _, - requestAttributes: GenericRequest[_, _] => Attributes = OpenTelemetryDefaults.requestAttributesWithFullUrl _, - responseAttributes: (GenericRequest[_, _], Response[_]) => Attributes = - OpenTelemetryDefaults.responseAttributes _, - errorAttributes: Throwable => Attributes = OpenTelemetryDefaults.errorAttributes _ + spanName: GenericRequest[?, ?] => String = OpenTelemetryDefaults.spanName, + requestAttributes: GenericRequest[?, ?] => Attributes = OpenTelemetryDefaults.requestAttributesWithFullUrl, + responseAttributes: (GenericRequest[?, ?], Response[?]) => Attributes = OpenTelemetryDefaults.responseAttributes, + errorAttributes: Throwable => Attributes = OpenTelemetryDefaults.errorAttributes ): OpenTelemetryTracingConfig = OpenTelemetryTracingConfig( tracer, diff --git a/observability/opentelemetry-backend/src/test/scala/sttp/client4/opentelemetry/OpenTelemetryMetricsBackendTest.scala b/observability/opentelemetry-backend/src/test/scala/sttp/client4/opentelemetry/OpenTelemetryMetricsBackendTest.scala index f03664f76c..91353e8b48 100644 --- a/observability/opentelemetry-backend/src/test/scala/sttp/client4/opentelemetry/OpenTelemetryMetricsBackendTest.scala +++ b/observability/opentelemetry-backend/src/test/scala/sttp/client4/opentelemetry/OpenTelemetryMetricsBackendTest.scala @@ -253,7 +253,7 @@ class OpenTelemetryMetricsBackendTest extends AnyFlatSpec with Matchers with Opt specTest(metrics, expectedMetricName) } - private[this] def getMetricValue(reader: InMemoryMetricReader, name: String): Option[Long] = + private def getMetricValue(reader: InMemoryMetricReader, name: String): Option[Long] = reader .collectAllMetrics() .asScala @@ -261,7 +261,7 @@ class OpenTelemetryMetricsBackendTest extends AnyFlatSpec with Matchers with Opt .map(_.getLongSumData) .map(_.getPoints.asScala.head.getValue) - private[this] def getHistogramValue(reader: InMemoryMetricReader, name: String): Option[HistogramPointData] = + private def getHistogramValue(reader: InMemoryMetricReader, name: String): Option[HistogramPointData] = reader .collectAllMetrics() .asScala @@ -269,7 +269,7 @@ class OpenTelemetryMetricsBackendTest extends AnyFlatSpec with Matchers with Opt .map(_.getHistogramData) .map(_.getPoints.asScala.head) - private[this] def getMetricResource(reader: InMemoryMetricReader, name: String): MetricData = + private def getMetricResource(reader: InMemoryMetricReader, name: String): MetricData = reader .collectAllMetrics() .asScala @@ -297,7 +297,7 @@ class OpenTelemetryMetricsBackendTest extends AnyFlatSpec with Matchers with Opt val reader = InMemoryMetricReader.create() val config = OpenTelemetryMetricsConfig( spawnNewOpenTelemetry(reader), - requestAttributes = OpenTelemetryDefaults.requestAttributesWithFullUrl _ + requestAttributes = OpenTelemetryDefaults.requestAttributesWithFullUrl ) val backend = OpenTelemetryMetricsBackend(stubAlwaysOk, config) @@ -312,7 +312,7 @@ class OpenTelemetryMetricsBackendTest extends AnyFlatSpec with Matchers with Opt } } - private[this] def specTest(metrics: List[MetricData], expectedMetricName: String): Unit = { + private def specTest(metrics: List[MetricData], expectedMetricName: String): Unit = { val metric = metrics.find(_.getName == expectedMetricName) assert( metric.isDefined, diff --git a/observability/opentelemetry-tracing-zio-backend/src/main/scala/sttp/client4/opentelemetry/zio/OpenTelemetryTracingZioBackend.scala b/observability/opentelemetry-tracing-zio-backend/src/main/scala/sttp/client4/opentelemetry/zio/OpenTelemetryTracingZioBackend.scala index da65b468d4..e80763fedc 100644 --- a/observability/opentelemetry-tracing-zio-backend/src/main/scala/sttp/client4/opentelemetry/zio/OpenTelemetryTracingZioBackend.scala +++ b/observability/opentelemetry-tracing-zio-backend/src/main/scala/sttp/client4/opentelemetry/zio/OpenTelemetryTracingZioBackend.scala @@ -18,7 +18,7 @@ abstract class OpenTelemetryTracingZioBackend[+P]( tracing: Tracing ) extends DelegateBackend[Task, P](delegate) with Backend[Task] { - def send[T](request: GenericRequest[T, P with Effect[Task]]): Task[Response[T]] = + def send[T](request: GenericRequest[T, P & Effect[Task]]): Task[Response[T]] = ZIO.scoped { val carrier = OutgoingContextCarrier.default() for { diff --git a/observability/opentelemetry-tracing-zio-backend/src/test/scala/sttp/client4/opentelemetry/zio/OpenTelemetryTracingZioBackendTest.scala b/observability/opentelemetry-tracing-zio-backend/src/test/scala/sttp/client4/opentelemetry/zio/OpenTelemetryTracingZioBackendTest.scala index fa39b97f6d..7caa62b1c6 100644 --- a/observability/opentelemetry-tracing-zio-backend/src/test/scala/sttp/client4/opentelemetry/zio/OpenTelemetryTracingZioBackendTest.scala +++ b/observability/opentelemetry-tracing-zio-backend/src/test/scala/sttp/client4/opentelemetry/zio/OpenTelemetryTracingZioBackendTest.scala @@ -19,7 +19,7 @@ import scala.collection.mutable class OpenTelemetryTracingZioBackendTest extends AnyFlatSpec with Matchers with BeforeAndAfter with ZioTestBase { - private val recordedRequests = mutable.ListBuffer[GenericRequest[_, _]]() + private val recordedRequests = mutable.ListBuffer[GenericRequest[?, ?]]() private val spanExporter = InMemorySpanExporter.create() diff --git a/observability/otel4s-metrics-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/Otel4sMetricsBackend.scala b/observability/otel4s-metrics-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/Otel4sMetricsBackend.scala index 97b849b33c..bf1e0f1d1a 100644 --- a/observability/otel4s-metrics-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/Otel4sMetricsBackend.scala +++ b/observability/otel4s-metrics-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/Otel4sMetricsBackend.scala @@ -116,24 +116,24 @@ object Otel4sMetricsBackend { responseBodySize: Histogram[F, Long], activeRequests: UpDownCounter[F, Long], dispatcher: Dispatcher[F], - urlTemplate: GenericRequest[_, _] => Option[String], - extraAttributes: GenericRequest[_, _] => Attributes + urlTemplate: GenericRequest[?, ?] => Option[String], + extraAttributes: GenericRequest[?, ?] => Attributes ) extends RequestListener[F, State] { - def before(request: GenericRequest[_, _]): F[State] = + def before(request: GenericRequest[?, ?]): F[State] = for { start <- Clock[F].realTime attributes <- Monad[F].pure(activeRequestAttributes(request)) _ <- activeRequests.inc(attributes) } yield State(start, attributes) - def responseBodyReceived(request: GenericRequest[_, _], response: ResponseMetadata, state: State): Unit = + def responseBodyReceived(request: GenericRequest[?, ?], response: ResponseMetadata, state: State): Unit = dispatcher.unsafeRunAndForget(captureResponseMetrics(request, response, state)) def responseHandled( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], response: ResponseMetadata, state: State, - exception: Option[ResponseException[_]] + exception: Option[ResponseException[?]] ): F[Unit] = { // responseBodyReceived is not called for WebSocket requests // ignoring the tag as there's no point in capturing timing information for WebSockets @@ -141,7 +141,7 @@ object Otel4sMetricsBackend { } def exception( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], state: State, e: Throwable, responseBodyReceivedCalled: Boolean @@ -157,7 +157,7 @@ object Otel4sMetricsBackend { } private def captureResponseMetrics( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], response: ResponseMetadata, state: State ): F[Unit] = @@ -170,7 +170,7 @@ object Otel4sMetricsBackend { _ <- activeRequests.dec(state.activeRequestsAttributes) } yield () - private def activeRequestAttributes(request: GenericRequest[_, _]): Attributes = { + private def activeRequestAttributes(request: GenericRequest[?, ?]): Attributes = { val b = Attributes.newBuilder b ++= extraAttributes(request) @@ -184,7 +184,7 @@ object Otel4sMetricsBackend { b.result() } - private def fullAttributes(request: GenericRequest[_, _], response: ResponseMetadata): Attributes = + private def fullAttributes(request: GenericRequest[?, ?], response: ResponseMetadata): Attributes = fullAttributes( request, Some(response.code), @@ -192,7 +192,7 @@ object Otel4sMetricsBackend { ) private def fullAttributes( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], responseStatusCode: Option[StatusCode], errorType: Option[String] ): Attributes = { diff --git a/observability/otel4s-metrics-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/Otel4sMetricsConfig.scala b/observability/otel4s-metrics-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/Otel4sMetricsConfig.scala index 7f3a7fc2d1..3d6c7be863 100644 --- a/observability/otel4s-metrics-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/Otel4sMetricsConfig.scala +++ b/observability/otel4s-metrics-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/Otel4sMetricsConfig.scala @@ -8,8 +8,8 @@ final case class Otel4sMetricsConfig( requestDurationHistogramBuckets: BucketBoundaries, requestBodySizeHistogramBuckets: Option[BucketBoundaries], responseBodySizeHistogramBuckets: Option[BucketBoundaries], - urlTemplate: GenericRequest[_, _] => Option[String] = (_) => None, - extraAttributes: GenericRequest[_, _] => Attributes = (_) => Attributes.empty + urlTemplate: GenericRequest[?, ?] => Option[String] = (_) => None, + extraAttributes: GenericRequest[?, ?] => Attributes = (_) => Attributes.empty ) object Otel4sMetricsConfig { diff --git a/observability/otel4s-metrics-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/UrlTemplates.scala b/observability/otel4s-metrics-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/UrlTemplates.scala index 043919a259..e358ae52f0 100644 --- a/observability/otel4s-metrics-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/UrlTemplates.scala +++ b/observability/otel4s-metrics-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/UrlTemplates.scala @@ -10,7 +10,7 @@ object UrlTemplates { /** URL template function that replaces numeric IDs and UUIDs in path segments and query values with `{id}`. Always * returns `Some` — the template equals the original URL when no IDs are found. */ - val replaceIds: GenericRequest[_, _] => Option[String] = request => { + val replaceIds: GenericRequest[?, ?] => Option[String] = request => { val uri = request.uri val templatedSegments = uri.pathSegments.segments.map(s => if (IdRegex.matches(s.v)) IdPlaceholder else s.v) diff --git a/observability/otel4s-tracing-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/Otel4sTracingBackend.scala b/observability/otel4s-tracing-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/Otel4sTracingBackend.scala index 92a9353663..4baca51036 100644 --- a/observability/otel4s-tracing-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/Otel4sTracingBackend.scala +++ b/observability/otel4s-tracing-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/Otel4sTracingBackend.scala @@ -17,7 +17,7 @@ private class Otel4sTracingBackend[F[_]: MonadCancelThrow: Tracer, P]( ) extends DelegateBackend[F, P](delegate) with Backend[F] { - def send[T](request: GenericRequest[T, P with capabilities.Effect[F]]): F[Response[T]] = + def send[T](request: GenericRequest[T, P & capabilities.Effect[F]]): F[Response[T]] = MonadCancelThrow[F].uncancelable { poll => Tracer[F] .spanBuilder(config.spanName(request)) diff --git a/observability/otel4s-tracing-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/Otel4sTracingConfig.scala b/observability/otel4s-tracing-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/Otel4sTracingConfig.scala index 848d95966b..08f57b1657 100644 --- a/observability/otel4s-tracing-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/Otel4sTracingConfig.scala +++ b/observability/otel4s-tracing-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/Otel4sTracingConfig.scala @@ -4,9 +4,9 @@ import org.typelevel.otel4s.Attributes import sttp.client4.{GenericRequest, Response} final case class Otel4sTracingConfig( - spanName: GenericRequest[_, _] => String, - requestAttributes: GenericRequest[_, _] => Attributes, - responseAttributes: Response[_] => Attributes, + spanName: GenericRequest[?, ?] => String, + requestAttributes: GenericRequest[?, ?] => Attributes, + responseAttributes: Response[?] => Attributes, errorAttributes: Throwable => Attributes ) diff --git a/observability/otel4s-tracing-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/Otel4sTracingDefaults.scala b/observability/otel4s-tracing-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/Otel4sTracingDefaults.scala index df643bec97..b28c401f16 100644 --- a/observability/otel4s-tracing-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/Otel4sTracingDefaults.scala +++ b/observability/otel4s-tracing-backend/src/main/scala/sttp/client4/opentelemetry/otel4s/Otel4sTracingDefaults.scala @@ -16,7 +16,7 @@ object Otel4sTracingDefaults { /** @see https://opentelemetry.io/docs/specs/semconv/http/http-spans/#name */ def spanName( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], uriTemplateClassifier: Uri => Option[Uri] = Function.const(None) ): String = { val method = request.method.method @@ -30,7 +30,7 @@ object Otel4sTracingDefaults { * https://opentelemetry.io/docs/specs/semconv/http/http-metrics/#http-client */ def requestAttributes( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], uriRedactor: Uri => Option[Uri] = redactedUserInfo, headersAsAttributes: Set[String] = Set.empty ): Attributes = { @@ -59,7 +59,7 @@ object Otel4sTracingDefaults { } /** @see https://opentelemetry.io/docs/specs/semconv/http/http-metrics/#http-client */ - def responseAttributes(response: Response[_], headersAsAttributes: Set[String] = Set.empty): Attributes = { + def responseAttributes(response: Response[?], headersAsAttributes: Set[String] = Set.empty): Attributes = { val b = Attributes.newBuilder if (!response.code.isSuccess) { diff --git a/observability/prometheus-backend/src/main/scala/sttp/client4/prometheus/PrometheusBackend.scala b/observability/prometheus-backend/src/main/scala/sttp/client4/prometheus/PrometheusBackend.scala index 20736dd919..412d1a16ec 100644 --- a/observability/prometheus-backend/src/main/scala/sttp/client4/prometheus/PrometheusBackend.scala +++ b/observability/prometheus-backend/src/main/scala/sttp/client4/prometheus/PrometheusBackend.scala @@ -65,13 +65,13 @@ object PrometheusBackend { private def listener(config: PrometheusConfig): PrometheusListener = new PrometheusListener( - (req: GenericRequest[_, _]) => config.requestToHistogramNameMapper(req), - (req: GenericRequest[_, _]) => config.requestToInProgressGaugeNameMapper(req), - (rr: (GenericRequest[_, _], ResponseMetadata)) => config.responseToSuccessCounterMapper(rr._1, rr._2), - (rr: (GenericRequest[_, _], ResponseMetadata)) => config.responseToErrorCounterMapper(rr._1, rr._2), - (r: (GenericRequest[_, _], Throwable)) => config.requestToFailureCounterMapper(r._1, r._2), - (req: GenericRequest[_, _]) => config.requestToSizeSummaryMapper(req), - (rr: (GenericRequest[_, _], ResponseMetadata)) => config.responseToSizeSummaryMapper(rr._1, rr._2), + (req: GenericRequest[?, ?]) => config.requestToHistogramNameMapper(req), + (req: GenericRequest[?, ?]) => config.requestToInProgressGaugeNameMapper(req), + (rr: (GenericRequest[?, ?], ResponseMetadata)) => config.responseToSuccessCounterMapper(rr._1, rr._2), + (rr: (GenericRequest[?, ?], ResponseMetadata)) => config.responseToErrorCounterMapper(rr._1, rr._2), + (r: (GenericRequest[?, ?], Throwable)) => config.requestToFailureCounterMapper(r._1, r._2), + (req: GenericRequest[?, ?]) => config.requestToSizeSummaryMapper(req), + (rr: (GenericRequest[?, ?], ResponseMetadata)) => config.responseToSizeSummaryMapper(rr._1, rr._2), config.prometheusRegistry, cacheFor(histograms, config.prometheusRegistry), cacheFor(gauges, config.prometheusRegistry), @@ -86,7 +86,7 @@ object PrometheusBackend { * @return * The modified collector config. The config can be used when configuring the backend using [[apply]]. */ - def addMethodLabel[T <: BaseCollectorConfig](config: T, req: GenericRequest[_, _]): config.T = { + def addMethodLabel[T <: BaseCollectorConfig](config: T, req: GenericRequest[?, ?]): config.T = { val methodLabel: Option[(String, String)] = if (config.labels.map(_._1.toLowerCase).contains(DefaultMethodLabel)) { None @@ -168,13 +168,13 @@ object PrometheusBackend { } class PrometheusListener( - histogramNameMapper: GenericRequest[_, _] => Option[HistogramCollectorConfig], - inProgressGaugeNameMapper: GenericRequest[_, _] => Option[CollectorConfig], - successCounterMapper: ((GenericRequest[_, _], ResponseMetadata)) => Option[CollectorConfig], - errorCounterMapper: ((GenericRequest[_, _], ResponseMetadata)) => Option[CollectorConfig], - failureCounterMapper: ((GenericRequest[_, _], Throwable)) => Option[CollectorConfig], - requestToSizeSummaryMapper: GenericRequest[_, _] => Option[CollectorConfig], - responseToSizeSummaryMapper: ((GenericRequest[_, _], ResponseMetadata)) => Option[CollectorConfig], + histogramNameMapper: GenericRequest[?, ?] => Option[HistogramCollectorConfig], + inProgressGaugeNameMapper: GenericRequest[?, ?] => Option[CollectorConfig], + successCounterMapper: ((GenericRequest[?, ?], ResponseMetadata)) => Option[CollectorConfig], + errorCounterMapper: ((GenericRequest[?, ?], ResponseMetadata)) => Option[CollectorConfig], + failureCounterMapper: ((GenericRequest[?, ?], Throwable)) => Option[CollectorConfig], + requestToSizeSummaryMapper: GenericRequest[?, ?] => Option[CollectorConfig], + responseToSizeSummaryMapper: ((GenericRequest[?, ?], ResponseMetadata)) => Option[CollectorConfig], prometheusRegistry: PrometheusRegistry, histogramsCache: ConcurrentHashMap[String, Histogram], gaugesCache: ConcurrentHashMap[String, Gauge], @@ -182,15 +182,15 @@ class PrometheusListener( summariesCache: ConcurrentHashMap[String, Summary] ) extends RequestListener[Identity, RequestCollectors] { - override def before(request: GenericRequest[_, _]): RequestCollectors = { + override def before(request: GenericRequest[?, ?]): RequestCollectors = { val requestTimer: Option[Timer] = for { histogramData <- histogramNameMapper(request) histogram: Histogram = getOrCreateMetric(histogramsCache, histogramData, createNewHistogram) - } yield histogram.labelValues(histogramData.labelValues: _*).startTimer() + } yield histogram.labelValues(histogramData.labelValues*).startTimer() val gauge: Option[GaugeDataPoint] = for { gaugeData <- inProgressGaugeNameMapper(request) - } yield getOrCreateMetric(gaugesCache, gaugeData, createNewGauge).labelValues(gaugeData.labelValues: _*) + } yield getOrCreateMetric(gaugesCache, gaugeData, createNewGauge).labelValues(gaugeData.labelValues*) observeRequestContentLengthSummaryIfMapped(request, requestToSizeSummaryMapper) @@ -200,7 +200,7 @@ class PrometheusListener( } private def captureResponseMetrics( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], response: ResponseMetadata, requestCollectors: RequestCollectors ): Unit = { @@ -216,16 +216,16 @@ class PrometheusListener( } override def responseBodyReceived( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], response: ResponseMetadata, requestCollectors: RequestCollectors ): Unit = captureResponseMetrics(request, response, requestCollectors) override def responseHandled( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], response: ResponseMetadata, requestCollectors: RequestCollectors, - e: Option[ResponseException[_]] + e: Option[ResponseException[?]] ): Unit = { // responseBodyReceived is not called for WebSocket requests // ignoring the timer as there's no point in capturing timing information for WebSockets @@ -233,7 +233,7 @@ class PrometheusListener( } override def exception( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], requestCollectors: RequestCollectors, e: Throwable, responseBodyReceivedCalled: Boolean @@ -250,27 +250,27 @@ class PrometheusListener( mapper: T => Option[BaseCollectorConfig] ): Unit = mapper(request).foreach { data => - getOrCreateMetric(countersCache, data, createNewCounter).labelValues(data.labelValues: _*).inc() + getOrCreateMetric(countersCache, data, createNewCounter).labelValues(data.labelValues*).inc() } private def observeResponseContentLengthSummaryIfMapped( - request: GenericRequest[_, _], + request: GenericRequest[?, ?], response: ResponseMetadata, - mapper: ((GenericRequest[_, _], ResponseMetadata)) => Option[BaseCollectorConfig] + mapper: ((GenericRequest[?, ?], ResponseMetadata)) => Option[BaseCollectorConfig] ): Unit = mapper((request, response)).foreach { data => response.contentLength.map(_.toDouble).foreach { size => - getOrCreateMetric(summariesCache, data, createNewSummary).labelValues(data.labelValues: _*).observe(size) + getOrCreateMetric(summariesCache, data, createNewSummary).labelValues(data.labelValues*).observe(size) } } private def observeRequestContentLengthSummaryIfMapped( - request: GenericRequest[_, _], - mapper: GenericRequest[_, _] => Option[BaseCollectorConfig] + request: GenericRequest[?, ?], + mapper: GenericRequest[?, ?] => Option[BaseCollectorConfig] ): Unit = mapper(request).foreach { data => (request.contentLength: Option[Long]).map(_.toDouble).foreach { size => - getOrCreateMetric(summariesCache, data, createNewSummary).labelValues(data.labelValues: _*).observe(size) + getOrCreateMetric(summariesCache, data, createNewSummary).labelValues(data.labelValues*).observe(size) } } @@ -290,9 +290,9 @@ class PrometheusListener( Histogram .builder() .unit(data.unit) - .classicUpperBounds(data.buckets: _*) + .classicUpperBounds(data.buckets*) .name(data.collectorName) - .labelNames(data.labelNames: _*) + .labelNames(data.labelNames*) .help(data.help) .register(prometheusRegistry) @@ -300,7 +300,7 @@ class PrometheusListener( Gauge .builder() .name(data.collectorName) - .labelNames(data.labelNames: _*) + .labelNames(data.labelNames*) .help(data.help) .register(prometheusRegistry) @@ -308,7 +308,7 @@ class PrometheusListener( Counter .builder() .name(data.collectorName) - .labelNames(data.labelNames: _*) + .labelNames(data.labelNames*) .help(data.help) .register(prometheusRegistry) @@ -316,7 +316,7 @@ class PrometheusListener( Summary .builder() .name(data.collectorName) - .labelNames(data.labelNames: _*) + .labelNames(data.labelNames*) .help(data.help) .register(prometheusRegistry) } diff --git a/observability/prometheus-backend/src/main/scala/sttp/client4/prometheus/PrometheusConfig.scala b/observability/prometheus-backend/src/main/scala/sttp/client4/prometheus/PrometheusConfig.scala index 5114fb7fe1..35163099b5 100644 --- a/observability/prometheus-backend/src/main/scala/sttp/client4/prometheus/PrometheusConfig.scala +++ b/observability/prometheus-backend/src/main/scala/sttp/client4/prometheus/PrometheusConfig.scala @@ -6,24 +6,24 @@ import sttp.client4.prometheus.PrometheusBackend._ import sttp.model.ResponseMetadata final case class PrometheusConfig( - requestToHistogramNameMapper: GenericRequest[_, _] => Option[HistogramCollectorConfig] = - (req: GenericRequest[_, _]) => Some(addMethodLabel(HistogramCollectorConfig(DefaultHistogramName), req)), - requestToInProgressGaugeNameMapper: GenericRequest[_, _] => Option[CollectorConfig] = (req: GenericRequest[_, _]) => + requestToHistogramNameMapper: GenericRequest[?, ?] => Option[HistogramCollectorConfig] = + (req: GenericRequest[?, ?]) => Some(addMethodLabel(HistogramCollectorConfig(DefaultHistogramName), req)), + requestToInProgressGaugeNameMapper: GenericRequest[?, ?] => Option[CollectorConfig] = (req: GenericRequest[?, ?]) => Some(addMethodLabel(CollectorConfig(DefaultRequestsActiveGaugeName), req)), - responseToSuccessCounterMapper: (GenericRequest[_, _], ResponseMetadata) => Option[CollectorConfig] = - (req: GenericRequest[_, _], resp: ResponseMetadata) => + responseToSuccessCounterMapper: (GenericRequest[?, ?], ResponseMetadata) => Option[CollectorConfig] = + (req: GenericRequest[?, ?], resp: ResponseMetadata) => Some(addStatusLabel(addMethodLabel(CollectorConfig(DefaultSuccessCounterName), req), resp)), - responseToErrorCounterMapper: (GenericRequest[_, _], ResponseMetadata) => Option[CollectorConfig] = - (req: GenericRequest[_, _], resp: ResponseMetadata) => + responseToErrorCounterMapper: (GenericRequest[?, ?], ResponseMetadata) => Option[CollectorConfig] = + (req: GenericRequest[?, ?], resp: ResponseMetadata) => Some(addStatusLabel(addMethodLabel(CollectorConfig(DefaultErrorCounterName), req), resp)), - requestToFailureCounterMapper: (GenericRequest[_, _], Throwable) => Option[CollectorConfig] = ( - req: GenericRequest[_, _], + requestToFailureCounterMapper: (GenericRequest[?, ?], Throwable) => Option[CollectorConfig] = ( + req: GenericRequest[?, ?], _: Throwable ) => Some(addMethodLabel(CollectorConfig(DefaultFailureCounterName), req)), - requestToSizeSummaryMapper: GenericRequest[_, _] => Option[CollectorConfig] = (req: GenericRequest[_, _]) => + requestToSizeSummaryMapper: GenericRequest[?, ?] => Option[CollectorConfig] = (req: GenericRequest[?, ?]) => Some(addMethodLabel(CollectorConfig(DefaultRequestSizeName), req)), - responseToSizeSummaryMapper: (GenericRequest[_, _], ResponseMetadata) => Option[CollectorConfig] = - (req: GenericRequest[_, _], resp: ResponseMetadata) => + responseToSizeSummaryMapper: (GenericRequest[?, ?], ResponseMetadata) => Option[CollectorConfig] = + (req: GenericRequest[?, ?], resp: ResponseMetadata) => Some(addStatusLabel(addMethodLabel(CollectorConfig(DefaultResponseSizeName), req), resp)), prometheusRegistry: PrometheusRegistry = PrometheusRegistry.defaultRegistry ) diff --git a/observability/prometheus-backend/src/test/scala/sttp/client4/prometheus/PrometheusBackendTest.scala b/observability/prometheus-backend/src/test/scala/sttp/client4/prometheus/PrometheusBackendTest.scala index 7e95709396..594af6cdc6 100644 --- a/observability/prometheus-backend/src/test/scala/sttp/client4/prometheus/PrometheusBackendTest.scala +++ b/observability/prometheus-backend/src/test/scala/sttp/client4/prometheus/PrometheusBackendTest.scala @@ -429,7 +429,7 @@ class PrometheusBackendTest val HostLabel = "Host" def addHostLabel[T <: BaseCollectorConfig]( config: T, - req: GenericRequest[_, _], + req: GenericRequest[?, ?], resp: ResponseMetadata ): config.T = { val hostLabel: Option[(String, String)] = @@ -442,7 +442,7 @@ class PrometheusBackendTest val backend = PrometheusBackend( backendStub, PrometheusConfig.Default.copy( - responseToErrorCounterMapper = (req: GenericRequest[_, _], resp: ResponseMetadata) => + responseToErrorCounterMapper = (req: GenericRequest[?, ?], resp: ResponseMetadata) => Some(addHostLabel(addMethodLabel(CollectorConfig(PrometheusBackend.DefaultErrorCounterName), req), req, resp)) ) ) @@ -457,13 +457,13 @@ class PrometheusBackendTest ).map(_.getValue) shouldBe Some(1) } - private[this] def getMetricSnapshot[T](name: String): Option[T] = + private def getMetricSnapshot[T](name: String): Option[T] = Option(PrometheusRegistry.defaultRegistry.scrape((s: String) => s.equals(name))) .filter(_.size() > 0) .map(_.get(0).getDataPoints.get(0)) .map(_.asInstanceOf[T]) - private[this] def getMetricValue[T <: DataPointSnapshot](name: String, labels: List[(String, String)]): Option[T] = { + private def getMetricValue[T <: DataPointSnapshot](name: String, labels: List[(String, String)]): Option[T] = { val condition = Labels.of(labels.map(_._1).toArray, labels.map(_._2).toArray) Option(PrometheusRegistry.defaultRegistry.scrape((s: String) => s.equals(name))) .filter(_.size() > 0) diff --git a/okhttp-backend/monix/src/main/scala/sttp/client4/okhttp/monix/OkHttpMonixBackend.scala b/okhttp-backend/monix/src/main/scala/sttp/client4/okhttp/monix/OkHttpMonixBackend.scala index 6b963320ae..0f2d9d242c 100644 --- a/okhttp-backend/monix/src/main/scala/sttp/client4/okhttp/monix/OkHttpMonixBackend.scala +++ b/okhttp-backend/monix/src/main/scala/sttp/client4/okhttp/monix/OkHttpMonixBackend.scala @@ -34,7 +34,7 @@ class OkHttpMonixBackend private ( webSocketBufferCapacity: Option[Int] )(implicit s: Scheduler -) extends OkHttpAsyncBackend[Task, MonixStreams, MonixStreams with WebSockets]( +) extends OkHttpAsyncBackend[Task, MonixStreams, MonixStreams & WebSockets]( client, TaskMonadAsyncError, closeClient, @@ -69,7 +69,7 @@ class OkHttpMonixBackend private ( override def compileWebSocketPipe( ws: WebSocket[Task], - pipe: streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame] + pipe: streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame] ): Task[Unit] = MonixWebSockets.compilePipe(ws, pipe) } @@ -96,7 +96,7 @@ class OkHttpMonixBackend private ( } }) - var value: T = _ + var value: T = null.asInstanceOf[T] override def hasNext: Boolean = blockingQueue.take() match { @@ -133,7 +133,7 @@ object OkHttpMonixBackend { s: Scheduler ): WebSocketStreamBackend[Task, MonixStreams] = FollowRedirectsBackend( - new OkHttpMonixBackend(client, closeClient, compressionHandlers, webSocketBufferCapacity)(s) + new OkHttpMonixBackend(client, closeClient, compressionHandlers, webSocketBufferCapacity) ) def apply( @@ -149,7 +149,7 @@ object OkHttpMonixBackend { closeClient = true, compressionHandlers, webSocketBufferCapacity - )(s) + ) ) def resource( @@ -170,7 +170,7 @@ object OkHttpMonixBackend { s: Scheduler = Scheduler.global ): Resource[Task, WebSocketStreamBackend[Task, MonixStreams]] = Resource.make( - Task.eval(OkHttpMonixBackend(client, closeClient = true, compressionHandlers, webSocketBufferCapacity)(s)) + Task.eval(OkHttpMonixBackend(client, closeClient = true, compressionHandlers, webSocketBufferCapacity)) )(_.close()) def usingClient( @@ -178,7 +178,7 @@ object OkHttpMonixBackend { compressionHandlers: CompressionHandlers[Any, InputStream] = DefaultCompressionHandlers, webSocketBufferCapacity: Option[Int] = OkHttpBackend.DefaultWebSocketBufferCapacity )(implicit s: Scheduler = Scheduler.global): WebSocketStreamBackend[Task, MonixStreams] = - OkHttpMonixBackend(client, closeClient = false, compressionHandlers, webSocketBufferCapacity)(s) + OkHttpMonixBackend(client, closeClient = false, compressionHandlers, webSocketBufferCapacity) /** Create a stub backend for testing, which uses the [[Task]] response wrapper, and supports `Observable[ByteBuffer]` * streaming. diff --git a/okhttp-backend/monix/src/test/scala/sttp/client4/okhttp/monix/OkHttpMonixWebSocketTest.scala b/okhttp-backend/monix/src/test/scala/sttp/client4/okhttp/monix/OkHttpMonixWebSocketTest.scala index fd89f8bd45..5be8c8aaa8 100644 --- a/okhttp-backend/monix/src/test/scala/sttp/client4/okhttp/monix/OkHttpMonixWebSocketTest.scala +++ b/okhttp-backend/monix/src/test/scala/sttp/client4/okhttp/monix/OkHttpMonixWebSocketTest.scala @@ -34,8 +34,8 @@ class OkHttpMonixWebSocketTest override def bufferCapacity: Int = OkHttpBackend.DefaultWebSocketBufferCapacity.get override def functionToPipe( - f: WebSocketFrame.Data[_] => Option[WebSocketFrame] - ): Observable[WebSocketFrame.Data[_]] => Observable[WebSocketFrame] = + f: WebSocketFrame.Data[?] => Option[WebSocketFrame] + ): Observable[WebSocketFrame.Data[?]] => Observable[WebSocketFrame] = in => in.concatMapIterable(m => f(m).toList) override def eventually[T](interval: FiniteDuration, attempts: Int)(f: => Task[T]): Task[T] = @@ -43,11 +43,11 @@ class OkHttpMonixWebSocketTest override def fromTextPipe( function: String => WebSocketFrame - ): Observable[WebSocketFrame.Data[_]] => Observable[WebSocketFrame] = MonixWebSockets.fromTextPipe(function) + ): Observable[WebSocketFrame.Data[?]] => Observable[WebSocketFrame] = MonixWebSockets.fromTextPipe(function) override def prepend(item: WebSocketFrame.Text)( - to: Observable[WebSocketFrame.Data[_]] => Observable[WebSocketFrame] - ): Observable[WebSocketFrame.Data[_]] => Observable[WebSocketFrame] = + to: Observable[WebSocketFrame.Data[?]] => Observable[WebSocketFrame] + ): Observable[WebSocketFrame.Data[?]] => Observable[WebSocketFrame] = to.andThen(rest => Observable.now(item) ++ rest) override def concurrently[T](fs: List[() => Task[T]]): Task[List[T]] = Task.parSequence(fs.map(_())) diff --git a/okhttp-backend/src/main/scala/sttp/client4/okhttp/BodyFromOkHttp.scala b/okhttp-backend/src/main/scala/sttp/client4/okhttp/BodyFromOkHttp.scala index 7aca33e5e6..c0fef4e175 100644 --- a/okhttp-backend/src/main/scala/sttp/client4/okhttp/BodyFromOkHttp.scala +++ b/okhttp-backend/src/main/scala/sttp/client4/okhttp/BodyFromOkHttp.scala @@ -18,20 +18,20 @@ private[okhttp] trait BodyFromOkHttp[F[_], S] { def responseBodyToStream(inputStream: InputStream): streams.BinaryStream - private def fromWs[TT](r: GenericWebSocketResponseAs[TT, _], ws: WebSocket[F], meta: ResponseMetadata): F[TT] = + private def fromWs[TT](r: GenericWebSocketResponseAs[TT, ?], ws: WebSocket[F], meta: ResponseMetadata): F[TT] = r match { case ResponseAsWebSocket(f) => f.asInstanceOf[(WebSocket[F], ResponseMetadata) => F[TT]](ws, meta).ensure(ws.close()) case ResponseAsWebSocketUnsafe() => ws.unit.asInstanceOf[F[TT]] case ResponseAsWebSocketStream(_, p) => - compileWebSocketPipe(ws, p.asInstanceOf[streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame]]) + compileWebSocketPipe(ws, p.asInstanceOf[streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame]]) } - def compileWebSocketPipe(ws: WebSocket[F], pipe: streams.Pipe[WebSocketFrame.Data[_], WebSocketFrame]): F[Unit] + def compileWebSocketPipe(ws: WebSocket[F], pipe: streams.Pipe[WebSocketFrame.Data[?], WebSocketFrame]): F[Unit] def apply[T]( responseBody: InputStream, - responseAs: ResponseAsDelegate[T, _], + responseAs: ResponseAsDelegate[T, ?], responseMetadata: ResponseMetadata, ws: Option[WebSocket[F]] ): F[T] = bodyFromResponseAs(responseAs, responseMetadata, ws.toRight(responseBody)) @@ -70,7 +70,7 @@ private[okhttp] trait BodyFromOkHttp[F[_], S] { override protected def regularAsInputStream(response: InputStream): F[InputStream] = monad.unit(response) override protected def handleWS[T]( - responseAs: GenericWebSocketResponseAs[T, _], + responseAs: GenericWebSocketResponseAs[T, ?], meta: ResponseMetadata, ws: WebSocket[F] ): F[T] = fromWs(responseAs, ws, meta) diff --git a/okhttp-backend/src/main/scala/sttp/client4/okhttp/BodyToOkHttp.scala b/okhttp-backend/src/main/scala/sttp/client4/okhttp/BodyToOkHttp.scala index 0975b1b238..2f5a7247c3 100644 --- a/okhttp-backend/src/main/scala/sttp/client4/okhttp/BodyToOkHttp.scala +++ b/okhttp-backend/src/main/scala/sttp/client4/okhttp/BodyToOkHttp.scala @@ -46,7 +46,7 @@ private[okhttp] trait BodyToOkHttp[F[_], S] { } } - private def addMultipart(builder: OkHttpMultipartBody.Builder, mp: Part[GenericRequestBody[_]]): Unit = { + private def addMultipart(builder: OkHttpMultipartBody.Builder, mp: Part[GenericRequestBody[?]]): Unit = { val allHeaders = mp.headers :+ Header(HeaderNames.ContentDisposition, mp.contentDispositionHeaderValue) val headers = OkHttpHeaders.of(allHeaders.filterNot(_.is(HeaderNames.ContentType)).map(h => (h.name, h.value)).toMap.asJava) diff --git a/okhttp-backend/src/main/scala/sttp/client4/okhttp/OkHttpBackend.scala b/okhttp-backend/src/main/scala/sttp/client4/okhttp/OkHttpBackend.scala index d0e36473a1..a4fe45b2c9 100644 --- a/okhttp-backend/src/main/scala/sttp/client4/okhttp/OkHttpBackend.scala +++ b/okhttp-backend/src/main/scala/sttp/client4/okhttp/OkHttpBackend.scala @@ -35,7 +35,7 @@ abstract class OkHttpBackend[F[_], S <: Streams[S], P]( with Backend[F] { val streams: Streams[S] - type R = P with Effect[F] + type R = P & Effect[F] override def send[T](request: GenericRequest[T, R]): F[Response[T]] = adjustExceptions(request.isWebSocket, request) { @@ -49,7 +49,7 @@ abstract class OkHttpBackend[F[_], S <: Streams[S], P]( protected def sendRegular[T](request: GenericRequest[T, R]): F[Response[T]] protected def sendWebSocket[T](request: GenericRequest[T, R]): F[Response[T]] - private def adjustExceptions[T](isWebsocket: Boolean, request: GenericRequest[_, _])(t: => F[T]): F[T] = + private def adjustExceptions[T](isWebsocket: Boolean, request: GenericRequest[?, ?])(t: => F[T]): F[T] = SttpClientException.adjustExceptions(monad)(t)( OkHttpBackend.exceptionToSttpClientException(isWebsocket, request, _) ) @@ -85,7 +85,7 @@ abstract class OkHttpBackend[F[_], S <: Streams[S], P]( private[okhttp] def readResponse[T]( res: OkHttpResponse, - request: GenericRequest[_, R], + request: GenericRequest[?, R], responseAs: ResponseAsDelegate[T, R], isWebSocket: Boolean ): F[Response[T]] = { @@ -179,7 +179,7 @@ object OkHttpBackend { private[okhttp] def exceptionToSttpClientException( isWebsocket: Boolean, - request: GenericRequest[_, _], + request: GenericRequest[?, ?], e: Exception ): Option[Exception] = e match { diff --git a/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/BodyFromPekko.scala b/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/BodyFromPekko.scala index d042593bb7..3f9964123d 100644 --- a/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/BodyFromPekko.scala +++ b/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/BodyFromPekko.scala @@ -72,7 +72,7 @@ private[pekkohttp] class BodyFromPekko()(implicit ec: ExecutionContext, mat: Mat ) override protected def handleWS[T]( - responseAs: GenericWebSocketResponseAs[T, _], + responseAs: GenericWebSocketResponseAs[T, ?], meta: ResponseMetadata, ws: Promise[Flow[Message, Message, NotUsed]] ): Future[T] = wsFromPekko(responseAs, ws, meta) @@ -109,7 +109,7 @@ private[pekkohttp] class BodyFromPekko()(implicit ec: ExecutionContext, mat: Mat val flow = Flow[Message] .mapAsync(1)(messageToFrame) - .via(p.asInstanceOf[PekkoStreams.Pipe[WebSocketFrame.Data[_], WebSocketFrame]]) + .via(p.asInstanceOf[PekkoStreams.Pipe[WebSocketFrame.Data[?], WebSocketFrame]]) .takeWhile { case WebSocketFrame.Close(_, _) => false case _ => true @@ -191,7 +191,7 @@ private[pekkohttp] class BodyFromPekko()(implicit ec: ExecutionContext, mat: Mat override def isOpen(): Future[Boolean] = Future.successful(open.get()) - override implicit def monad: MonadError[Future] = new FutureMonad()(ec) + override implicit def monad: MonadError[Future] = new FutureMonad() } (flow, ws) @@ -199,7 +199,7 @@ private[pekkohttp] class BodyFromPekko()(implicit ec: ExecutionContext, mat: Mat private def messageToFrame( m: Message - )(implicit ec: ExecutionContext, mat: Materializer): Future[WebSocketFrame.Data[_]] = + )(implicit ec: ExecutionContext, mat: Materializer): Future[WebSocketFrame.Data[?]] = m match { case msg: TextMessage => msg.textStream.runFold("")(_ + _).map(t => WebSocketFrame.text(t)) diff --git a/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/BodyToPekko.scala b/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/BodyToPekko.scala index 7fe41f335d..0a1a2783c6 100644 --- a/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/BodyToPekko.scala +++ b/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/BodyToPekko.scala @@ -22,7 +22,7 @@ import sttp.client4.compression.Compressor private[pekkohttp] object BodyToPekko { def apply[R]( - r: GenericRequest[_, R], + r: GenericRequest[?, R], ar: HttpRequest, compressors: List[Compressor[R]] ): Try[HttpRequest] = { @@ -34,7 +34,7 @@ private[pekkohttp] object BodyToPekko { val (body, contentLength) = Compressor.compressIfNeeded(r, compressors) - def toBodyPart(mp: Part[BodyPart[_]]): Try[PekkoMultipart.FormData.BodyPart] = { + def toBodyPart(mp: Part[BodyPart[?]]): Try[PekkoMultipart.FormData.BodyPart] = { def streamPartEntity(contentType: ContentType, s: PekkoStreams.BinaryStream) = mp.contentLength match { case None => HttpEntity.IndefiniteLength(contentType, s) @@ -82,11 +82,11 @@ private[pekkohttp] object BodyToPekko { } private def multipartEntity( - r: GenericRequest[_, _], + r: GenericRequest[?, ?], bodyParts: Seq[PekkoMultipart.FormData.BodyPart] ): Try[RequestEntity] = r.headers.find(Util.isContentType) match { - case None => Success(PekkoMultipart.FormData(bodyParts: _*).toEntity) + case None => Success(PekkoMultipart.FormData(bodyParts*).toEntity) case Some(ct) => Util.parseContentType(ct.value).map(_.mediaType).flatMap { case m: MediaType.Multipart => diff --git a/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/FromPekko.scala b/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/FromPekko.scala index 2263b34640..76b01e1d64 100644 --- a/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/FromPekko.scala +++ b/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/FromPekko.scala @@ -17,7 +17,7 @@ private[pekkohttp] object FromPekko { ch :: (cl.toList ++ other) } - def exception(request: GenericRequest[_, _], e: Exception): Option[Exception] = + def exception(request: GenericRequest[?, ?], e: Exception): Option[Exception] = e match { case e: pekko.stream.ConnectionException => Some(new SttpClientException.ConnectException(request, e)) case e: pekko.stream.StreamTcpException => diff --git a/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/PekkoHttpBackend.scala b/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/PekkoHttpBackend.scala index 06f9487ec3..61ea5c054d 100644 --- a/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/PekkoHttpBackend.scala +++ b/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/PekkoHttpBackend.scala @@ -17,7 +17,6 @@ import org.apache.pekko.http.scaladsl.model.ws.ValidUpgrade import org.apache.pekko.http.scaladsl.model.ws.WebSocketRequest import org.apache.pekko.http.scaladsl.model.{StatusCode => _, _} import org.apache.pekko.http.scaladsl.settings.ConnectionPoolSettings -import org.apache.pekko.stream.Materializer import org.apache.pekko.stream.scaladsl.Flow import org.apache.pekko.stream.scaladsl.Sink import org.apache.pekko.util.ByteString @@ -51,7 +50,7 @@ class PekkoHttpBackend private ( customizeResponse: (HttpRequest, HttpResponse) => HttpResponse, compressionHandlers: CompressionHandlers[PekkoStreams, HttpResponse] ) extends WebSocketStreamBackend[Future, PekkoStreams] { - type R = PekkoStreams with WebSockets with Effect[Future] + type R = PekkoStreams & WebSockets & Effect[Future] private implicit val as: ActorSystem = actorSystem private implicit val _ec: ExecutionContext = ec @@ -115,9 +114,9 @@ class PekkoHttpBackend private ( .recoverWith { case _ => Future.failed(t) } } - override val monad: MonadError[Future] = new FutureMonad()(ec) + override val monad: MonadError[Future] = new FutureMonad() - private def connectionSettings(r: GenericRequest[_, _]): ConnectionPoolSettings = { + private def connectionSettings(r: GenericRequest[?, ?]): ConnectionPoolSettings = { val connectionPoolSettingsWithProxy = opts.proxy match { case Some(p) if r.uri.host.forall(!p.ignoreProxy(_)) => val clientTransport = p.auth match { @@ -135,7 +134,10 @@ class PekkoHttpBackend private ( .withUpdatedConnectionSettings(_.withIdleTimeout(r.options.readTimeout)) } - private lazy val bodyFromPekko = new BodyFromPekko()(ec, implicitly[Materializer], monad) + private lazy val bodyFromPekko = { + implicit val m: MonadError[Future] = monad + new BodyFromPekko() + } private def responseFromPekko[T]( r: GenericRequest[T, R], @@ -194,7 +196,7 @@ class PekkoHttpBackend private ( Decompressor.decompressIfPossible(response, encoding.value, compressionHandlers.decompressors) } - private def adjustExceptions[T](request: GenericRequest[_, _])(t: => Future[T]): Future[T] = + private def adjustExceptions[T](request: GenericRequest[?, ?])(t: => Future[T]): Future[T] = SttpClientException.adjustExceptions(monad)(t)(FromPekko.exception(request, _)) override def close(): Future[Unit] = @@ -340,6 +342,6 @@ object PekkoHttpBackend { */ def stub(implicit ec: ExecutionContext = ExecutionContext.global - ): WebSocketStreamBackendStub[Future, PekkoStreams with WebSockets] = + ): WebSocketStreamBackendStub[Future, PekkoStreams & WebSockets] = WebSocketStreamBackendStub(new FutureMonad()) } diff --git a/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/PekkoHttpClient.scala b/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/PekkoHttpClient.scala index c0efd288b2..9f99d13bb0 100644 --- a/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/PekkoHttpClient.scala +++ b/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/PekkoHttpClient.scala @@ -33,7 +33,7 @@ object PekkoHttpClient { customLog: Option[LoggingAdapter] ): PekkoHttpClient = new PekkoHttpClient { - private val http = Http()(system) + private val http = Http(system) override def singleRequest( request: HttpRequest, diff --git a/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/ToPekko.scala b/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/ToPekko.scala index c03b6a279a..a8860b7b1d 100644 --- a/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/ToPekko.scala +++ b/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/ToPekko.scala @@ -10,7 +10,7 @@ import scala.collection.immutable.Seq import scala.util.{Failure, Success, Try} private[pekkohttp] object ToPekko { - def request(r: GenericRequest[_, _]): Try[HttpRequest] = { + def request(r: GenericRequest[?, ?]): Try[HttpRequest] = { val ar = HttpRequest(uri = r.uri.toString, method = method(r.method)) ToPekko.headers(r.headers).map(ar.withHeaders) } diff --git a/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/Util.scala b/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/Util.scala index bcd3ebeb43..e94372b3f6 100644 --- a/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/Util.scala +++ b/pekko-http-backend/src/main/scala/sttp/client4/pekkohttp/Util.scala @@ -13,14 +13,13 @@ import scala.util.{Failure, Success, Try} private[pekkohttp] object Util { def traverseTry[T](l: Seq[Try[T]]): Try[Seq[T]] = { // https://stackoverflow.com/questions/15495678/flatten-scala-try - val (ss: Seq[Success[T]] @unchecked, fs: Seq[Failure[T]] @unchecked) = - l.partition(_.isSuccess) + val (ss, fs) = l.partition(_.isSuccess) if (fs.isEmpty) Success(ss.map(_.get)) - else Failure[Seq[T]](fs.head.exception) + else Failure[Seq[T]](fs.head.failed.get) } - def parseContentTypeOrOctetStream(r: GenericRequest[_, _]): Try[ContentType] = + def parseContentTypeOrOctetStream(r: GenericRequest[?, ?]): Try[ContentType] = parseContentTypeOrOctetStream( r.headers .find(isContentType) diff --git a/pekko-http-backend/src/test/scala/sttp/client4/pekkohttp/PekkoHttpWebSocketTest.scala b/pekko-http-backend/src/test/scala/sttp/client4/pekkohttp/PekkoHttpWebSocketTest.scala index 562939af4c..0294c2d47d 100644 --- a/pekko-http-backend/src/test/scala/sttp/client4/pekkohttp/PekkoHttpWebSocketTest.scala +++ b/pekko-http-backend/src/test/scala/sttp/client4/pekkohttp/PekkoHttpWebSocketTest.scala @@ -23,17 +23,17 @@ class PekkoHttpWebSocketTest override implicit val monad: MonadError[Future] = new FutureMonad override def functionToPipe( - f: WebSocketFrame.Data[_] => Option[WebSocketFrame] - ): Flow[WebSocketFrame.Data[_], WebSocketFrame, Any] = - Flow.fromFunction(f).mapConcat(_.toList): Flow[WebSocketFrame.Data[_], WebSocketFrame, Any] + f: WebSocketFrame.Data[?] => Option[WebSocketFrame] + ): Flow[WebSocketFrame.Data[?], WebSocketFrame, Any] = + Flow.fromFunction(f).mapConcat(_.toList): Flow[WebSocketFrame.Data[?], WebSocketFrame, Any] override def prepend( item: WebSocketFrame.Text - )(to: Flow[WebSocketFrame.Data[_], WebSocketFrame, Any]): Flow[WebSocketFrame.Data[_], WebSocketFrame, Any] = + )(to: Flow[WebSocketFrame.Data[?], WebSocketFrame, Any]): Flow[WebSocketFrame.Data[?], WebSocketFrame, Any] = to.prepend(Source(List(item))) - override def fromTextPipe(function: String => WebSocketFrame): Flow[WebSocketFrame.Data[_], WebSocketFrame, Any] = - Flow[WebSocketFrame.Data[_]].collect { case tf: WebSocketFrame.Text => function(tf.payload) } + override def fromTextPipe(function: String => WebSocketFrame): Flow[WebSocketFrame.Data[?], WebSocketFrame, Any] = + Flow[WebSocketFrame.Data[?]].collect { case tf: WebSocketFrame.Text => function(tf.payload) } override def concurrently[T](fs: List[() => Future[T]]): Future[List[T]] = Future.sequence(fs.map(_())) }