diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5df46b269d..084a67e0f2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - scala: [2.12.18, 2.13.12, 3.3.1] + scala: [2.12.19, 2.13.14, 3.3.3] java: - graal_graalvm@17 - graal_graalvm@21 @@ -76,8 +76,8 @@ jobs: cache: sbt - name: Check formatting - if: matrix.scala == '2.13.12' - run: sbt ++2.13.12 fmtCheck + if: matrix.scala == '2.13.14' + run: sbt ++2.13.14 fmtCheck - name: Check that workflows are up to date run: sbt '++ ${{ matrix.scala }}' githubWorkflowCheck @@ -87,10 +87,10 @@ jobs: - name: Check doc generation if: ${{ github.event_name == 'pull_request' }} - run: sbt ++2.13.12 doc + run: sbt ++2.13.14 doc - name: zio-http-shaded Tests - if: matrix.scala == '2.13.12' + if: matrix.scala == '2.13.14' env: PUBLISH_SHADED: true run: sbt '++ ${{ matrix.scala }}' zioHttpShadedTests/test @@ -111,7 +111,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - scala: [2.13.12] + scala: [2.13.14] java: [graal_graalvm@17] runs-on: ${{ matrix.os }} steps: @@ -156,32 +156,32 @@ jobs: java-version: 21 cache: sbt - - name: Download target directories (2.12.18) + - name: Download target directories (2.12.19) uses: actions/download-artifact@v4 with: - name: target-${{ matrix.os }}-2.12.18-${{ matrix.java }} + name: target-${{ matrix.os }}-2.12.19-${{ matrix.java }} - - name: Inflate target directories (2.12.18) + - name: Inflate target directories (2.12.19) run: | tar xf targets.tar rm targets.tar - - name: Download target directories (2.13.12) + - name: Download target directories (2.13.14) uses: actions/download-artifact@v4 with: - name: target-${{ matrix.os }}-2.13.12-${{ matrix.java }} + name: target-${{ matrix.os }}-2.13.14-${{ matrix.java }} - - name: Inflate target directories (2.13.12) + - name: Inflate target directories (2.13.14) run: | tar xf targets.tar rm targets.tar - - name: Download target directories (3.3.1) + - name: Download target directories (3.3.3) uses: actions/download-artifact@v4 with: - name: target-${{ matrix.os }}-3.3.1-${{ matrix.java }} + name: target-${{ matrix.os }}-3.3.3-${{ matrix.java }} - - name: Inflate target directories (3.3.1) + - name: Inflate target directories (3.3.3) run: | tar xf targets.tar rm targets.tar @@ -222,7 +222,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - scala: [2.13.12] + scala: [2.13.14] java: [temurin@8] runs-on: ${{ matrix.os }} steps: @@ -233,7 +233,7 @@ jobs: - name: Add Scoverage id: add_plugin - run: sed -i -e '$aaddSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.9")' project/plugins.sbt + run: sed -i -e '$aaddSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.12")' project/plugins.sbt - name: Update Build Definition id: update_build_definition @@ -255,7 +255,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - scala: [2.13.12] + scala: [2.13.14] java: [temurin@8] runs-on: ${{ matrix.os }} steps: @@ -274,7 +274,7 @@ jobs: GITHUB_TOKEN: ${{secrets.ACTIONS_PAT}} run: | cd zio-http - sed -i -e '$aaddSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.3")' project/plugins.sbt + sed -i -e '$aaddSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.7")' project/plugins.sbt cat > Main_CachedDateHeaderBenchmark.txt sbt -no-colors -v "zioHttpBenchmarks/jmh:run -i 3 -wi 3 -f1 -t1 CachedDateHeaderBenchmark" | grep -e "thrpt" -e "avgt" >> ../Main_CachedDateHeaderBenchmark.txt @@ -289,7 +289,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - scala: [2.13.12] + scala: [2.13.14] java: [temurin@8] runs-on: ${{ matrix.os }} steps: @@ -308,7 +308,7 @@ jobs: GITHUB_TOKEN: ${{secrets.ACTIONS_PAT}} run: | cd zio-http - sed -i -e '$aaddSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.3")' project/plugins.sbt + sed -i -e '$aaddSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.7")' project/plugins.sbt cat > Main_CookieDecodeBenchmark.txt sbt -no-colors -v "zioHttpBenchmarks/jmh:run -i 3 -wi 3 -f1 -t1 CookieDecodeBenchmark" | grep -e "thrpt" -e "avgt" >> ../Main_CookieDecodeBenchmark.txt @@ -323,7 +323,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - scala: [2.13.12] + scala: [2.13.14] java: [temurin@8] runs-on: ${{ matrix.os }} steps: @@ -342,7 +342,7 @@ jobs: GITHUB_TOKEN: ${{secrets.ACTIONS_PAT}} run: | cd zio-http - sed -i -e '$aaddSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.3")' project/plugins.sbt + sed -i -e '$aaddSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.7")' project/plugins.sbt cat > Main_EndpointBenchmark.txt sbt -no-colors -v "zioHttpBenchmarks/jmh:run -i 3 -wi 3 -f1 -t1 EndpointBenchmark" | grep -e "thrpt" -e "avgt" >> ../Main_EndpointBenchmark.txt @@ -357,7 +357,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - scala: [2.13.12] + scala: [2.13.14] java: [temurin@8] runs-on: ${{ matrix.os }} steps: @@ -376,7 +376,7 @@ jobs: GITHUB_TOKEN: ${{secrets.ACTIONS_PAT}} run: | cd zio-http - sed -i -e '$aaddSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.3")' project/plugins.sbt + sed -i -e '$aaddSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.7")' project/plugins.sbt cat > Main_HttpCollectEval.txt sbt -no-colors -v "zioHttpBenchmarks/jmh:run -i 3 -wi 3 -f1 -t1 HttpCollectEval" | grep -e "thrpt" -e "avgt" >> ../Main_HttpCollectEval.txt @@ -391,7 +391,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - scala: [2.13.12] + scala: [2.13.14] java: [temurin@8] runs-on: ${{ matrix.os }} steps: @@ -410,7 +410,7 @@ jobs: GITHUB_TOKEN: ${{secrets.ACTIONS_PAT}} run: | cd zio-http - sed -i -e '$aaddSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.3")' project/plugins.sbt + sed -i -e '$aaddSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.7")' project/plugins.sbt cat > Main_HttpCombineEval.txt sbt -no-colors -v "zioHttpBenchmarks/jmh:run -i 3 -wi 3 -f1 -t1 HttpCombineEval" | grep -e "thrpt" -e "avgt" >> ../Main_HttpCombineEval.txt @@ -425,7 +425,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - scala: [2.13.12] + scala: [2.13.14] java: [temurin@8] runs-on: ${{ matrix.os }} steps: @@ -444,7 +444,7 @@ jobs: GITHUB_TOKEN: ${{secrets.ACTIONS_PAT}} run: | cd zio-http - sed -i -e '$aaddSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.3")' project/plugins.sbt + sed -i -e '$aaddSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.7")' project/plugins.sbt cat > Main_HttpNestedFlatMapEval.txt sbt -no-colors -v "zioHttpBenchmarks/jmh:run -i 3 -wi 3 -f1 -t1 HttpNestedFlatMapEval" | grep -e "thrpt" -e "avgt" >> ../Main_HttpNestedFlatMapEval.txt @@ -459,7 +459,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - scala: [2.13.12] + scala: [2.13.14] java: [temurin@8] runs-on: ${{ matrix.os }} steps: @@ -478,7 +478,7 @@ jobs: GITHUB_TOKEN: ${{secrets.ACTIONS_PAT}} run: | cd zio-http - sed -i -e '$aaddSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.3")' project/plugins.sbt + sed -i -e '$aaddSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.7")' project/plugins.sbt cat > Main_HttpRouteTextPerf.txt sbt -no-colors -v "zioHttpBenchmarks/jmh:run -i 3 -wi 3 -f1 -t1 HttpRouteTextPerf" | grep -e "thrpt" -e "avgt" >> ../Main_HttpRouteTextPerf.txt @@ -493,7 +493,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - scala: [2.13.12] + scala: [2.13.14] java: [temurin@8] runs-on: ${{ matrix.os }} steps: @@ -512,7 +512,7 @@ jobs: GITHUB_TOKEN: ${{secrets.ACTIONS_PAT}} run: | cd zio-http - sed -i -e '$aaddSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.3")' project/plugins.sbt + sed -i -e '$aaddSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.7")' project/plugins.sbt cat > Main_ProbeContentTypeBenchmark.txt sbt -no-colors -v "zioHttpBenchmarks/jmh:run -i 3 -wi 3 -f1 -t1 ProbeContentTypeBenchmark" | grep -e "thrpt" -e "avgt" >> ../Main_ProbeContentTypeBenchmark.txt @@ -527,7 +527,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - scala: [2.13.12] + scala: [2.13.14] java: [temurin@8] runs-on: ${{ matrix.os }} steps: @@ -546,7 +546,7 @@ jobs: GITHUB_TOKEN: ${{secrets.ACTIONS_PAT}} run: | cd zio-http - sed -i -e '$aaddSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.3")' project/plugins.sbt + sed -i -e '$aaddSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.7")' project/plugins.sbt cat > Main_SchemeDecodeBenchmark.txt sbt -no-colors -v "zioHttpBenchmarks/jmh:run -i 3 -wi 3 -f1 -t1 SchemeDecodeBenchmark" | grep -e "thrpt" -e "avgt" >> ../Main_SchemeDecodeBenchmark.txt @@ -561,7 +561,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - scala: [2.13.12] + scala: [2.13.14] java: [temurin@8] runs-on: ${{ matrix.os }} steps: @@ -580,7 +580,7 @@ jobs: GITHUB_TOKEN: ${{secrets.ACTIONS_PAT}} run: | cd zio-http - sed -i -e '$aaddSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.3")' project/plugins.sbt + sed -i -e '$aaddSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.7")' project/plugins.sbt cat > Main_ServerInboundHandlerBenchmark.txt sbt -no-colors -v "zioHttpBenchmarks/jmh:run -i 3 -wi 3 -f1 -t1 ServerInboundHandlerBenchmark" | grep -e "thrpt" -e "avgt" >> ../Main_ServerInboundHandlerBenchmark.txt @@ -595,7 +595,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - scala: [2.13.12] + scala: [2.13.14] java: [temurin@8] runs-on: ${{ matrix.os }} steps: @@ -614,7 +614,7 @@ jobs: GITHUB_TOKEN: ${{secrets.ACTIONS_PAT}} run: | cd zio-http - sed -i -e '$aaddSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.3")' project/plugins.sbt + sed -i -e '$aaddSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.7")' project/plugins.sbt cat > Main_UtilBenchmark.txt sbt -no-colors -v "zioHttpBenchmarks/jmh:run -i 3 -wi 3 -f1 -t1 UtilBenchmark" | grep -e "thrpt" -e "avgt" >> ../Main_UtilBenchmark.txt @@ -736,7 +736,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - scala: [2.13.12] + scala: [2.13.14] java: [temurin@8] runs-on: ${{ matrix.os }} steps: @@ -815,7 +815,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - scala: [2.13.12] + scala: [2.13.14] java: [temurin@8] runs-on: ${{ matrix.os }} steps: diff --git a/README.md b/README.md index 7fff69ecab..f2a68d3e0a 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ ZIO HTTP is a scala library for building http apps. It is powered by ZIO and [Ne Setup via `build.sbt`: ```scala -libraryDependencies += "dev.zio" %% "zio-http" % "3.0.0-RC6" +libraryDependencies += "dev.zio" %% "zio-http" % "3.0.0-RC7" ``` **NOTES ON VERSIONING:** diff --git a/project/BuildHelper.scala b/project/BuildHelper.scala index 80d96d53ce..f371e6200f 100644 --- a/project/BuildHelper.scala +++ b/project/BuildHelper.scala @@ -6,12 +6,12 @@ import xerial.sbt.Sonatype.autoImport.* import sbtcrossproject.CrossPlugin.autoImport.crossProjectPlatform object BuildHelper extends ScalaSettings { - val Scala212 = "2.12.18" - val Scala213 = "2.13.12" - val Scala3 = "3.3.1" - val ScoverageVersion = "2.0.9" - val JmhVersion = "0.4.3" - val SilencerVersion = "1.7.14" + val Scala212 = "2.12.19" + val Scala213 = "2.13.14" + val Scala3 = "3.3.3" + val ScoverageVersion = "2.0.12" + val JmhVersion = "0.4.7" + val SilencerVersion = "1.7.17" private val stdOptions = Seq( "-deprecation", diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 14177ad14b..63937065b4 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -1,10 +1,10 @@ import sbt.* object Dependencies { - val JwtCoreVersion = "9.1.1" - val NettyVersion = "4.1.101.Final" - val NettyIncubatorVersion = "0.0.24.Final" - val ScalaCompactCollectionVersion = "2.11.0" + val JwtCoreVersion = "10.0.1" + val NettyVersion = "4.1.109.Final" + val NettyIncubatorVersion = "0.0.25.Final" + val ScalaCompactCollectionVersion = "2.12.0" val ZioVersion = "2.1.1" val ZioCliVersion = "0.5.0" val ZioSchemaVersion = "1.1.1" @@ -15,7 +15,7 @@ object Dependencies { val `scala-compact-collection` = "org.scala-lang.modules" %% "scala-collection-compat" % ScalaCompactCollectionVersion val scalafmt = "org.scalameta" %% "scalafmt-dynamic" % "3.8.1" - val scalametaParsers = "org.scalameta" %% "parsers" % "4.9.3" + val scalametaParsers = "org.scalameta" %% "parsers" % "4.9.4" val netty = Seq( diff --git a/project/build.properties b/project/build.properties index abbbce5da4..081fdbbc76 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.9.8 +sbt.version=1.10.0 diff --git a/project/plugins.sbt b/project/plugins.sbt index 02f9d2c2b0..3dfe8c5cd2 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,13 +1,13 @@ -addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.11.0") -addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.0") -addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.6") -addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.6.3") +addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.12.1") +addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.2") +addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.7") +addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.6.4") addSbtPlugin("io.spray" % "sbt-revolver" % "0.10.0") -addSbtPlugin("com.github.sbt" % "sbt-github-actions" % "0.22.0") +addSbtPlugin("com.github.sbt" % "sbt-github-actions" % "0.23.0") addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.5.12") addSbtPlugin("dev.zio" % "zio-sbt-website" % "0.4.0-alpha.26") addSbtPlugin("de.heikoseeberger" % "sbt-header" % "5.10.0") -addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.9") +addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.12") addSbtPlugin("io.get-coursier" % "sbt-shading" % "2.1.4") addSbtPlugin("com.github.cb372" % "sbt-explicit-dependencies" % "0.3.1") addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.16.0") diff --git a/sbt-zio-http-grpc/src/main/scala/zio/http/grpc/ZIOHttpGRPCGen.scala b/sbt-zio-http-grpc/src/main/scala/zio/http/grpc/ZIOHttpGRPCGen.scala index b8a26d2cae..25bf62724e 100644 --- a/sbt-zio-http-grpc/src/main/scala/zio/http/grpc/ZIOHttpGRPCGen.scala +++ b/sbt-zio-http-grpc/src/main/scala/zio/http/grpc/ZIOHttpGRPCGen.scala @@ -15,7 +15,7 @@ object ZIOHttpGRPCGen extends CodeGenApp { def process(request: CodeGenRequest): CodeGenResponse = ProtobufGenerator.parseParameters(request.parameter) match { - case Right(params) => + case Right(_) => val services = request.filesToGenerate.flatMap(fromProtobuf(_).files) val schemas = services.map(getImplicitSchemas(_)).map { case (pkg, tpes) => schemasFile(pkg, tpes) @@ -24,7 +24,7 @@ object ZIOHttpGRPCGen extends CodeGenApp { schemas ++ services.map(fileToPluginCode(_)), Set(CodeGeneratorResponse.Feature.FEATURE_PROTO3_OPTIONAL), ) - case Left(error) => + case Left(error) => CodeGenResponse.fail(error) } diff --git a/zio-http-cli/src/main/scala/zio/http/endpoint/cli/HttpOptions.scala b/zio-http-cli/src/main/scala/zio/http/endpoint/cli/HttpOptions.scala index 05fad687fb..254afc8d74 100644 --- a/zio-http-cli/src/main/scala/zio/http/endpoint/cli/HttpOptions.scala +++ b/zio-http-cli/src/main/scala/zio/http/endpoint/cli/HttpOptions.scala @@ -93,7 +93,7 @@ private[cli] object HttpOptions { */ private def fromSchema(schema: zio.schema.Schema[_]): Options[Json] = { - implicit def toJson[A](options: Options[A]): Options[Json] = options.map(value => Json.Str(value.toString())) + implicit def toJson[A0](options: Options[A0]): Options[Json] = options.map(value => Json.Str(value.toString())) lazy val emptyJson: Options[Json] = Options.Empty.map(_ => Json.Obj()) diff --git a/zio-http-docs/src/main/scala/utils.scala b/zio-http-docs/src/main/scala/utils.scala index 49565bfca5..33be268c1b 100644 --- a/zio-http-docs/src/main/scala/utils.scala +++ b/zio-http-docs/src/main/scala/utils.scala @@ -7,7 +7,7 @@ object utils { try { Source.fromFile("../" + path) } catch { - case _ => Source.fromFile(path) + case _: Throwable => Source.fromFile(path) } if (lines.isEmpty) { diff --git a/zio-http-example/src/main/scala/example/MultipartFormData.scala b/zio-http-example/src/main/scala/example/MultipartFormData.scala index e3f4963342..47b8436c1f 100644 --- a/zio-http-example/src/main/scala/example/MultipartFormData.scala +++ b/zio-http-example/src/main/scala/example/MultipartFormData.scala @@ -1,5 +1,7 @@ package example +import scala.annotation.nowarn + import zio.{Chunk, Scope, ZIO, ZIOAppArgs, ZIOAppDefault} import zio.http._ @@ -41,6 +43,7 @@ object MultipartFormData extends ZIOAppDefault { }, ).sandbox + @nowarn("msg=dead code") private def program: ZIO[Client with Server with Scope, Throwable, Unit] = for { port <- Server.install(app) diff --git a/zio-http-example/src/main/scala/example/MultipartFormDataStreaming.scala b/zio-http-example/src/main/scala/example/MultipartFormDataStreaming.scala index 5c2fd39c8c..a66b6767c1 100644 --- a/zio-http-example/src/main/scala/example/MultipartFormDataStreaming.scala +++ b/zio-http-example/src/main/scala/example/MultipartFormDataStreaming.scala @@ -1,5 +1,7 @@ package example +import scala.annotation.nowarn + import zio._ import zio.stream.{ZSink, ZStream} @@ -63,6 +65,7 @@ object MultipartFormDataStreaming extends ZIOAppDefault { }, ).sandbox @@ Middleware.debug + @nowarn("msg=dead code") private def program: ZIO[Server, Throwable, Unit] = for { port <- Server.install(app) diff --git a/zio-http-example/src/main/scala/example/ServeOnAnyOpenPort.scala b/zio-http-example/src/main/scala/example/ServeOnAnyOpenPort.scala index 3a201f29b0..9eadd16977 100644 --- a/zio-http-example/src/main/scala/example/ServeOnAnyOpenPort.scala +++ b/zio-http-example/src/main/scala/example/ServeOnAnyOpenPort.scala @@ -1,5 +1,7 @@ package example +import scala.annotation.nowarn + import zio._ import zio.http._ @@ -10,6 +12,7 @@ object ServeOnAnyOpenPort extends ZIOAppDefault { Method.GET / "hello" -> handler(Response.text("Hello, World!")), ) + @nowarn("msg=dead code") val app = for { port <- Server.install(httpApp) _ <- ZIO.log(s"server started on port $port") diff --git a/zio-http-example/src/main/scala/example/WebSocketAdvanced.scala b/zio-http-example/src/main/scala/example/WebSocketAdvanced.scala index ee5e9e97e9..12c59fa42e 100644 --- a/zio-http-example/src/main/scala/example/WebSocketAdvanced.scala +++ b/zio-http-example/src/main/scala/example/WebSocketAdvanced.scala @@ -1,5 +1,7 @@ package example +import scala.annotation.nowarn + import zio._ import zio.http.ChannelEvent.{ExceptionCaught, Read, UserEvent, UserEventTriggered} @@ -85,6 +87,7 @@ object WebSocketAdvancedClient extends ZIOAppDefault { } yield () }.connect("ws://localhost:8080/subscriptions") + @nowarn("msg=dead code") override val run = (for { _ <- webSocketHandler diff --git a/zio-http-example/src/main/scala/example/endpoint/CliExamples.scala b/zio-http-example/src/main/scala/example/endpoint/CliExamples.scala index 1029a15658..da86cc4295 100644 --- a/zio-http-example/src/main/scala/example/endpoint/CliExamples.scala +++ b/zio-http-example/src/main/scala/example/endpoint/CliExamples.scala @@ -12,31 +12,32 @@ import zio.http.codec._ import zio.http.endpoint.cli._ import zio.http.endpoint.{Endpoint, EndpointExecutor} +final case class User( + @description("The unique identifier of the User") + id: Int, + @description("The user's name") + name: String, + @description("The user's email") + email: Option[String], +) +object User { + implicit val schema: Schema[User] = DeriveSchema.gen[User] +} +final case class Post( + @description("The unique identifier of the User") + userId: Int, + @description("The unique identifier of the Post") + postId: Int, + @description("The post's contents") + contents: String, +) +object Post { + implicit val schema: Schema[Post] = DeriveSchema.gen[Post] +} + trait TestCliEndpoints { import HttpCodec._ import zio.http.codec.PathCodec._ - final case class User( - @description("The unique identifier of the User") - id: Int, - @description("The user's name") - name: String, - @description("The user's email") - email: Option[String], - ) - object User { - implicit val schema: Schema[User] = DeriveSchema.gen[User] - } - final case class Post( - @description("The unique identifier of the User") - userId: Int, - @description("The unique identifier of the Post") - postId: Int, - @description("The post's contents") - contents: String, - ) - object Post { - implicit val schema: Schema[Post] = DeriveSchema.gen[Post] - } val getUser = Endpoint(Method.GET / "users" / int("userId") ?? Doc.p("The unique identifier of the user")) diff --git a/zio-http-example/src/main/scala/example/endpoint/EndpointWithMultipleUnifiedErrors.scala b/zio-http-example/src/main/scala/example/endpoint/EndpointWithMultipleUnifiedErrors.scala index ff19d0543f..a77305c81e 100644 --- a/zio-http-example/src/main/scala/example/endpoint/EndpointWithMultipleUnifiedErrors.scala +++ b/zio-http-example/src/main/scala/example/endpoint/EndpointWithMultipleUnifiedErrors.scala @@ -1,5 +1,7 @@ package example.endpoint +import scala.annotation.nowarn + import zio._ import zio.schema.{DeriveSchema, Schema} @@ -17,6 +19,7 @@ object EndpointWithMultipleUnifiedErrors extends ZIOAppDefault { implicit val schema: Schema[Book] = DeriveSchema.gen } + @nowarn("msg=parameter .* never used") abstract class AppError(message: String) case class BookNotFound(message: String, bookId: Int) extends AppError(message) diff --git a/zio-http-gen/src/main/scala/zio/http/gen/grpc/EndpointGen.scala b/zio-http-gen/src/main/scala/zio/http/gen/grpc/EndpointGen.scala index b9151a21f1..225cca2d04 100644 --- a/zio-http-gen/src/main/scala/zio/http/gen/grpc/EndpointGen.scala +++ b/zio-http-gen/src/main/scala/zio/http/gen/grpc/EndpointGen.scala @@ -57,7 +57,6 @@ object EndpointGen { method: Protobuf.Method, ): Code.EndpointCode = { val pathSegments = List(service, method.name).map(Code.PathSegmentCode.apply) - val imports = Nil val endpoint = Code.EndpointCode( method = Method.POST, pathPatternCode = Code.PathPatternCode(pathSegments), diff --git a/zio-http-gen/src/main/scala/zio/http/gen/openapi/EndpointGen.scala b/zio-http-gen/src/main/scala/zio/http/gen/openapi/EndpointGen.scala index 09827ad266..30a6184994 100644 --- a/zio-http-gen/src/main/scala/zio/http/gen/openapi/EndpointGen.scala +++ b/zio-http-gen/src/main/scala/zio/http/gen/openapi/EndpointGen.scala @@ -655,7 +655,7 @@ final case class EndpointGen() { case JsonSchema.ArrayType(Some(schema)) => schemaToCode(schema, openAPI, name, annotations) // TODO use additionalProperties - case JsonSchema.Object(properties, additionalProperties, required) => + case JsonSchema.Object(properties, _, required) => val fields = properties.map { case (name, schema) => val field = schemaToField(schema, openAPI, name, annotations) .getOrElse( diff --git a/zio-http-gen/src/test/scala/zio/http/gen/scala/CodeGenSpec.scala b/zio-http-gen/src/test/scala/zio/http/gen/scala/CodeGenSpec.scala index 0c372219e7..ab70e02c60 100644 --- a/zio-http-gen/src/test/scala/zio/http/gen/scala/CodeGenSpec.scala +++ b/zio-http-gen/src/test/scala/zio/http/gen/scala/CodeGenSpec.scala @@ -1,12 +1,11 @@ package zio.http.gen.scala -import java.io.File import java.nio.file._ +import scala.annotation.nowarn import scala.jdk.CollectionConverters._ import scala.meta._ import scala.meta.parsers._ -import scala.meta.prettyprinters.XtensionSyntax import scala.util.{Failure, Success, Try} import zio.Scope @@ -16,11 +15,11 @@ import zio.test._ import zio.http._ import zio.http.codec._ import zio.http.endpoint.Endpoint -import zio.http.endpoint.openapi.JsonSchema.SchemaStyle.Inline import zio.http.endpoint.openapi.{OpenAPI, OpenAPIGen} import zio.http.gen.model._ import zio.http.gen.openapi.EndpointGen +@nowarn("msg=missing interpolator") object CodeGenSpec extends ZIOSpecDefault { private def fileShouldBe(dir: java.nio.file.Path, subPath: String, expectedFile: String): TestResult = { diff --git a/zio-http-testkit/src/main/scala/zio/http/TestChannel.scala b/zio-http-testkit/src/main/scala/zio/http/TestChannel.scala index 6e3e118fa1..4f5a6c1e02 100644 --- a/zio-http-testkit/src/main/scala/zio/http/TestChannel.scala +++ b/zio-http-testkit/src/main/scala/zio/http/TestChannel.scala @@ -19,9 +19,9 @@ case class TestChannel( ): ZIO[Env, Err, Unit] = { lazy val loop: ZIO[Env, Err, Unit] = in.take.flatMap { - case event @ ChannelEvent.ExceptionCaught(_) => f(event).unit - case event @ ChannelEvent.Unregistered => f(event).unit - case event => f(event) *> ZIO.yieldNow *> loop + case event: ChannelEvent.ExceptionCaught => f(event).unit + case event: ChannelEvent.Unregistered.type => f(event).unit + case event => f(event) *> ZIO.yieldNow *> loop } loop diff --git a/zio-http-testkit/src/test/scala/zio/http/SocketContractSpec.scala b/zio-http-testkit/src/test/scala/zio/http/SocketContractSpec.scala index b5d026360d..834a826359 100644 --- a/zio-http-testkit/src/test/scala/zio/http/SocketContractSpec.scala +++ b/zio-http-testkit/src/test/scala/zio/http/SocketContractSpec.scala @@ -8,7 +8,6 @@ import zio.test._ import zio.http.ChannelEvent.{Read, Unregistered, UserEvent, UserEventTriggered} import zio.http.netty.NettyConfig import zio.http.netty.server.NettyDriver -import zio.http.{Headers, Status, Version, ZIOHttpSpec} object SocketContractSpec extends ZIOHttpSpec { diff --git a/zio-http-testkit/src/test/scala/zio/http/TestClientSpec.scala b/zio-http-testkit/src/test/scala/zio/http/TestClientSpec.scala index 07e198e551..e615dea0bf 100644 --- a/zio-http-testkit/src/test/scala/zio/http/TestClientSpec.scala +++ b/zio-http-testkit/src/test/scala/zio/http/TestClientSpec.scala @@ -3,8 +3,7 @@ package zio.http import zio._ import zio.test._ -import zio.http.ChannelEvent.{Read, UserEvent, UserEventTriggered} -import zio.http.{Method, Status, WebSocketFrame} +import zio.http.ChannelEvent.Read object TestClientSpec extends ZIOHttpSpec { def extractStatus(response: Response): Status = response.status diff --git a/zio-http/js/src/main/scala/zio/http/DriverPlatformSpecific.scala b/zio-http/js/src/main/scala/zio/http/DriverPlatformSpecific.scala index 17206ff897..2da617f677 100644 --- a/zio-http/js/src/main/scala/zio/http/DriverPlatformSpecific.scala +++ b/zio-http/js/src/main/scala/zio/http/DriverPlatformSpecific.scala @@ -1,7 +1,10 @@ package zio.http +import scala.annotation.nowarn + import zio.ZLayer +@nowarn("msg=dead code") trait DriverPlatformSpecific { val default: ZLayer[Server.Config, Throwable, Driver] = throw new UnsupportedOperationException("Not implemented for Scala.js") diff --git a/zio-http/js/src/main/scala/zio/http/ServerPlatformSpecific.scala b/zio-http/js/src/main/scala/zio/http/ServerPlatformSpecific.scala index dd91a062ae..87b50e6312 100644 --- a/zio-http/js/src/main/scala/zio/http/ServerPlatformSpecific.scala +++ b/zio-http/js/src/main/scala/zio/http/ServerPlatformSpecific.scala @@ -1,9 +1,12 @@ package zio.http +import scala.annotation.nowarn + import zio._ import zio.http.Server.Config +@nowarn("msg=dead code") trait ServerPlatformSpecific { val customized: ZLayer[Config, Throwable, Server] = throw new UnsupportedOperationException("Not implemented for Scala.js") diff --git a/zio-http/js/src/main/scala/zio/http/internal/BodyEncodingPlatformSpecific.scala b/zio-http/js/src/main/scala/zio/http/internal/BodyEncodingPlatformSpecific.scala index 4c116ce514..e6e89eb91b 100644 --- a/zio-http/js/src/main/scala/zio/http/internal/BodyEncodingPlatformSpecific.scala +++ b/zio-http/js/src/main/scala/zio/http/internal/BodyEncodingPlatformSpecific.scala @@ -1,5 +1,8 @@ package zio.http.internal +import scala.annotation.nowarn + +@nowarn("msg=dead code") trait BodyEncodingPlatformSpecific { val default: BodyEncoding = throw new NotImplementedError("No version implemented for Scala.js yet.") } diff --git a/zio-http/js/src/main/scala/zio/http/internal/CookieEncodingPlatformSpecific.scala b/zio-http/js/src/main/scala/zio/http/internal/CookieEncodingPlatformSpecific.scala index 907e99fe0e..7b45853993 100644 --- a/zio-http/js/src/main/scala/zio/http/internal/CookieEncodingPlatformSpecific.scala +++ b/zio-http/js/src/main/scala/zio/http/internal/CookieEncodingPlatformSpecific.scala @@ -1,5 +1,8 @@ package zio.http.internal +import scala.annotation.nowarn + +@nowarn("msg=dead code") private[http] trait CookieEncodingPlatformSpecific { val default: CookieEncoding = throw new NotImplementedError("No version implemented for Scala.js yet.") } diff --git a/zio-http/js/src/main/scala/zio/http/internal/DateEncodingPlatformSpecific.scala b/zio-http/js/src/main/scala/zio/http/internal/DateEncodingPlatformSpecific.scala index 51da19718f..bc7f236c27 100644 --- a/zio-http/js/src/main/scala/zio/http/internal/DateEncodingPlatformSpecific.scala +++ b/zio-http/js/src/main/scala/zio/http/internal/DateEncodingPlatformSpecific.scala @@ -1,5 +1,8 @@ package zio.http.internal +import scala.annotation.nowarn + +@nowarn("msg=dead code") private[http] trait DateEncodingPlatformSpecific { val default: DateEncoding = throw new NotImplementedError("No version implemented for Scala.js yet.") } diff --git a/zio-http/js/src/main/scala/zio/http/internal/FetchDriver.scala b/zio-http/js/src/main/scala/zio/http/internal/FetchDriver.scala index c135487e5a..ced813384a 100644 --- a/zio-http/js/src/main/scala/zio/http/internal/FetchDriver.scala +++ b/zio-http/js/src/main/scala/zio/http/internal/FetchDriver.scala @@ -1,5 +1,6 @@ package zio.http.internal +import scala.collection.compat.immutable.ArraySeq import scala.scalajs.js import scala.scalajs.js.typedarray.Uint8Array @@ -65,7 +66,7 @@ final case class FetchDriver() extends ZClient.Driver[Any, Throwable] { if (body.isEmpty) { ZIO.succeed(js.undefined) } else { - body.asArray.map { ar => Uint8Array.of(ar.map(_.toShort): _*) } + body.asArray.map { ar => Uint8Array.of(ArraySeq.unsafeWrapArray(ar.map(_.toShort)): _*) } } override def socket[Env1 <: Any](version: Version, url: URL, headers: Headers, app: WebSocketApp[Env1])(implicit diff --git a/zio-http/js/src/main/scala/zio/http/internal/HeaderEncodingPlatformSpecific.scala b/zio-http/js/src/main/scala/zio/http/internal/HeaderEncodingPlatformSpecific.scala index 54f443913c..efa9e8c225 100644 --- a/zio-http/js/src/main/scala/zio/http/internal/HeaderEncodingPlatformSpecific.scala +++ b/zio-http/js/src/main/scala/zio/http/internal/HeaderEncodingPlatformSpecific.scala @@ -1,5 +1,8 @@ package zio.http.internal +import scala.annotation.nowarn + +@nowarn("msg=dead code") private[http] trait HeaderEncodingPlatformSpecific { val default: HeaderEncoding = throw new NotImplementedError("No version implemented for Scala.js yet.") } diff --git a/zio-http/jvm/src/main/scala/zio/http/netty/AsyncBodyReader.scala b/zio-http/jvm/src/main/scala/zio/http/netty/AsyncBodyReader.scala index 5c481f7a31..db11dfa77b 100644 --- a/zio-http/jvm/src/main/scala/zio/http/netty/AsyncBodyReader.scala +++ b/zio-http/jvm/src/main/scala/zio/http/netty/AsyncBodyReader.scala @@ -19,7 +19,7 @@ package zio.http.netty import java.io.IOException import zio.stacktracer.TracingImplicits.disableAutoTrace -import zio.{Chunk, ChunkBuilder, Trace, Unsafe} +import zio.{Chunk, ChunkBuilder} import zio.http.netty.AsyncBodyReader.State import zio.http.netty.NettyBody.UnsafeAsync @@ -27,16 +27,15 @@ import zio.http.netty.NettyBody.UnsafeAsync import io.netty.buffer.ByteBufUtil import io.netty.channel.{ChannelHandlerContext, SimpleChannelInboundHandler} import io.netty.handler.codec.http.{HttpContent, LastHttpContent} -abstract class AsyncBodyReader(implicit trace: Trace) extends SimpleChannelInboundHandler[HttpContent](true) { - protected val unsafeClass: Unsafe = Unsafe.unsafe +abstract class AsyncBodyReader extends SimpleChannelInboundHandler[HttpContent](true) { private var state: State = State.Buffering private val buffer: ChunkBuilder[(Chunk[Byte], Boolean)] = ChunkBuilder.make[(Chunk[Byte], Boolean)]() private var previousAutoRead: Boolean = false private var ctx: ChannelHandlerContext = _ - def connect(callback: UnsafeAsync): Unit = { + private[zio] def connect(callback: UnsafeAsync): Unit = { this.synchronized { state match { case State.Buffering => @@ -51,7 +50,7 @@ abstract class AsyncBodyReader(implicit trace: Trace) extends SimpleChannelInbou result.foreach { case (chunk, isLast) => callback(chunk, isLast) } - ctx.read() + ctx.read(): Unit } else { throw new IllegalStateException("Attempting to read from a closed channel, which will never finish") } @@ -69,7 +68,7 @@ abstract class AsyncBodyReader(implicit trace: Trace) extends SimpleChannelInbou } override def handlerRemoved(ctx: ChannelHandlerContext): Unit = { - ctx.channel().config().setAutoRead(previousAutoRead) + val _ = ctx.channel().config().setAutoRead(previousAutoRead) } override def channelRead0( @@ -113,7 +112,7 @@ abstract class AsyncBodyReader(implicit trace: Trace) extends SimpleChannelInbou callback.fail(new IOException("Channel closed unexpectedly")) } } - ctx.fireChannelInactive() + ctx.fireChannelInactive(): Unit } } diff --git a/zio-http/jvm/src/main/scala/zio/http/netty/NettyBodyWriter.scala b/zio-http/jvm/src/main/scala/zio/http/netty/NettyBodyWriter.scala index 206f5aeda6..f63c20c044 100644 --- a/zio-http/jvm/src/main/scala/zio/http/netty/NettyBodyWriter.scala +++ b/zio-http/jvm/src/main/scala/zio/http/netty/NettyBodyWriter.scala @@ -16,10 +16,14 @@ package zio.http.netty +import scala.annotation.tailrec + import zio.Chunk.ByteArray import zio._ import zio.stacktracer.TracingImplicits.disableAutoTrace +import zio.stream.ZStream + import zio.http.Body import zio.http.Body._ import zio.http.netty.NettyBody.{AsciiStringBody, AsyncBody, ByteBufBody, UnsafeAsync} @@ -27,10 +31,17 @@ import zio.http.netty.NettyBody.{AsciiStringBody, AsyncBody, ByteBufBody, Unsafe import io.netty.buffer.Unpooled import io.netty.channel._ import io.netty.handler.codec.http.{DefaultHttpContent, LastHttpContent} +import io.netty.handler.stream.ChunkedNioFile object NettyBodyWriter { - def writeAndFlush(body: Body, contentLength: Option[Long], ctx: ChannelHandlerContext)(implicit + @tailrec + def writeAndFlush( + body: Body, + contentLength: Option[Long], + ctx: ChannelHandlerContext, + compressionEnabled: Boolean, + )(implicit trace: Trace, ): Option[Task[Unit]] = { @@ -46,19 +57,21 @@ object NettyBodyWriter { } body match { - case body: ByteBufBody => + case body: ByteBufBody => ctx.write(new DefaultHttpContent(body.byteBuf)) ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT) None - case body: FileBody => - val file = body.file - // Write the content. - ctx.write(new DefaultFileRegion(file, 0, body.fileSize)) - - // Write the end marker. + case body: FileBody if compressionEnabled => + // We need to stream the file when compression is enabled otherwise the response encoding fails + val stream = ZStream.fromFile(body.file) + val size = Some(body.fileSize) + val s = StreamBody(stream, knownContentLength = size, mediaType = body.mediaType) + NettyBodyWriter.writeAndFlush(s, size, ctx, compressionEnabled) + case body: FileBody => + ctx.write(new DefaultFileRegion(body.file, 0, body.fileSize)) ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT) None - case AsyncBody(async, _, _, _) => + case AsyncBody(async, _, _, _) => async( new UnsafeAsync { override def apply(message: Chunk[Byte], isLast: Boolean): Unit = { @@ -66,18 +79,18 @@ object NettyBodyWriter { case b: ByteArray => b.array case other => other.toArray } - writeArray(arr, isLast) + writeArray(arr, isLast): Unit } override def fail(cause: Throwable): Unit = - ctx.fireExceptionCaught(cause) + ctx.fireExceptionCaught(cause): Unit }, ) None - case AsciiStringBody(asciiString, _, _) => + case AsciiStringBody(asciiString, _, _) => writeArray(asciiString.array(), isLast = true) None - case StreamBody(stream, _, _, _) => + case StreamBody(stream, _, _, _) => Some( contentLength.orElse(body.knownContentLength) match { case Some(length) => @@ -118,13 +131,13 @@ object NettyBodyWriter { } }, ) - case ArrayBody(data, _, _) => + case ArrayBody(data, _, _) => writeArray(data, isLast = true) None - case ChunkBody(data, _, _) => + case ChunkBody(data, _, _) => writeArray(data.toArray, isLast = true) None - case EmptyBody => + case EmptyBody => ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT) None } diff --git a/zio-http/jvm/src/main/scala/zio/http/netty/NettyResponseEncoder.scala b/zio-http/jvm/src/main/scala/zio/http/netty/NettyResponseEncoder.scala index 6dbbc58994..b9a4fb0eb2 100644 --- a/zio-http/jvm/src/main/scala/zio/http/netty/NettyResponseEncoder.scala +++ b/zio-http/jvm/src/main/scala/zio/http/netty/NettyResponseEncoder.scala @@ -82,7 +82,9 @@ private[zio] object NettyResponseEncoder { */ private def maybeAddDateHeader(headers: HttpHeaders, status: Status): Unit = { if (status.isInformational || status.isServerError || headers.contains(HttpHeaderNames.DATE)) () - else headers.set(HttpHeaderNames.DATE, dateHeaderCache.get()) + else { + val _ = headers.set(HttpHeaderNames.DATE, dateHeaderCache.get()) + } } } diff --git a/zio-http/jvm/src/main/scala/zio/http/netty/WebSocketAppHandler.scala b/zio-http/jvm/src/main/scala/zio/http/netty/WebSocketAppHandler.scala index a473ed8a65..e56d5f9dcd 100644 --- a/zio-http/jvm/src/main/scala/zio/http/netty/WebSocketAppHandler.scala +++ b/zio-http/jvm/src/main/scala/zio/http/netty/WebSocketAppHandler.scala @@ -47,13 +47,14 @@ private[zio] final class WebSocketAppHandler( event: ChannelEvent[JWebSocketFrame], close: Boolean = false, ): Unit = { - zExec.runUninterruptible(ctx, NettyRuntime.noopEnsuring)( - queue.offer(event.map(frameFromNetty)) *> - (onComplete match { - case Some(promise) if close => promise.succeed(ChannelState.Invalid) - case _ => ZIO.unit - }), - ) + // IMPORTANT: Offering to the queue must be run synchronously to avoid messages being added in the wrong order + // Since the queue is unbounded, this will not block the event loop + // TODO: We need to come up with a design that doesn't involve running an effect to offer to the queue + zExec.unsafeRunSync(queue.offer(event.map(frameFromNetty))) + onComplete match { + case Some(promise) if close => promise.unsafe.done(Exit.succeed(ChannelState.Invalid)) + case _ => () + } } override def channelRead0(ctx: ChannelHandlerContext, msg: JWebSocketFrame): Unit = @@ -68,9 +69,8 @@ private[zio] final class WebSocketAppHandler( override def exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable): Unit = { dispatch(ctx, ChannelEvent.exceptionCaught(cause)) onComplete match { - case Some(promise) => - promise.fail(cause) - case None => + case Some(promise) => promise.unsafe.done(Exit.fail(cause)) + case None => () } } diff --git a/zio-http/jvm/src/main/scala/zio/http/netty/WebSocketChannel.scala b/zio-http/jvm/src/main/scala/zio/http/netty/WebSocketChannel.scala index 2c23337e81..af80fade0f 100644 --- a/zio-http/jvm/src/main/scala/zio/http/netty/WebSocketChannel.scala +++ b/zio-http/jvm/src/main/scala/zio/http/netty/WebSocketChannel.scala @@ -42,9 +42,9 @@ private[http] object WebSocketChannel { ): ZIO[Env, Err, Unit] = { lazy val loop: ZIO[Env, Err, Unit] = queue.take.flatMap { - case event @ ChannelEvent.ExceptionCaught(_) => f(event).unit - case event @ ChannelEvent.Unregistered => f(event).unit - case event => f(event) *> ZIO.yieldNow *> loop + case event: ChannelEvent.ExceptionCaught => f(event).unit + case event: ChannelEvent.Unregistered.type => f(event).unit + case event => f(event) *> ZIO.yieldNow *> loop } loop diff --git a/zio-http/jvm/src/main/scala/zio/http/netty/client/ClientInboundHandler.scala b/zio-http/jvm/src/main/scala/zio/http/netty/client/ClientInboundHandler.scala index 52424cc925..b1021d924e 100644 --- a/zio-http/jvm/src/main/scala/zio/http/netty/client/ClientInboundHandler.scala +++ b/zio-http/jvm/src/main/scala/zio/http/netty/client/ClientInboundHandler.scala @@ -40,23 +40,19 @@ final class ClientInboundHandler( extends SimpleChannelInboundHandler[HttpObject](false) { implicit private val unsafeClass: Unsafe = Unsafe.unsafe - override def handlerAdded(ctx: ChannelHandlerContext): Unit = { - super.handlerAdded(ctx) - } - - override def channelActive(ctx: ChannelHandlerContext): Unit = { - sendRequest(ctx) - } - - override def handlerRemoved(ctx: ChannelHandlerContext): Unit = super.handlerRemoved(ctx) + override def userEventTriggered(ctx: ChannelHandlerContext, evt: Any): Unit = + evt match { + case ClientInboundHandler.SendRequest => sendRequest(ctx) + case _ => ctx.fireUserEventTriggered(evt): Unit + } private def sendRequest(ctx: ChannelHandlerContext): Unit = { jReq match { case fullRequest: FullHttpRequest => - ctx.writeAndFlush(fullRequest) + ctx.writeAndFlush(fullRequest): Unit case _: HttpRequest => ctx.write(jReq) - NettyBodyWriter.writeAndFlush(req.body, None, ctx).foreach { effect => + NettyBodyWriter.writeAndFlush(req.body, None, ctx, compressionEnabled = false).foreach { effect => rtm.run(ctx, NettyRuntime.noopEnsuring)(effect)(Unsafe.unsafe, trace) } } @@ -77,5 +73,10 @@ final class ClientInboundHandler( override def exceptionCaught(ctx: ChannelHandlerContext, error: Throwable): Unit = { ctx.fireExceptionCaught(error) + () } } + +object ClientInboundHandler { + case object SendRequest +} diff --git a/zio-http/jvm/src/main/scala/zio/http/netty/client/ClientResponseStreamHandler.scala b/zio-http/jvm/src/main/scala/zio/http/netty/client/ClientResponseStreamHandler.scala index 75a71cfb15..b898944d4b 100644 --- a/zio-http/jvm/src/main/scala/zio/http/netty/client/ClientResponseStreamHandler.scala +++ b/zio-http/jvm/src/main/scala/zio/http/netty/client/ClientResponseStreamHandler.scala @@ -44,7 +44,7 @@ final class ClientResponseStreamHandler( onComplete.unsafe.done(Exit.succeed(ChannelState.forStatus(status))) else { onComplete.unsafe.done(Exit.succeed(ChannelState.Invalid)) - ctx.close() + ctx.close(): Unit } } } diff --git a/zio-http/jvm/src/main/scala/zio/http/netty/client/NettyClientDriver.scala b/zio-http/jvm/src/main/scala/zio/http/netty/client/NettyClientDriver.scala index 7755f05232..638740a08a 100644 --- a/zio-http/jvm/src/main/scala/zio/http/netty/client/NettyClientDriver.scala +++ b/zio-http/jvm/src/main/scala/zio/http/netty/client/NettyClientDriver.scala @@ -31,7 +31,7 @@ import zio.http.netty.socket.NettySocketProtocol import io.netty.channel.{Channel, ChannelFactory, ChannelFuture, ChannelHandler, EventLoopGroup} import io.netty.handler.codec.PrematureChannelClosureException import io.netty.handler.codec.http.websocketx.{WebSocketClientProtocolHandler, WebSocketFrame => JWebSocketFrame} -import io.netty.handler.codec.http.{FullHttpRequest, HttpObjectAggregator} +import io.netty.handler.codec.http.{FullHttpRequest, HttpObjectAggregator, HttpRequest} final case class NettyClientDriver private[netty] ( channelFactory: ChannelFactory[Channel], @@ -132,7 +132,7 @@ final case class NettyClientDriver private[netty] ( toRemove.add(clientFailureHandler) pipeline.fireChannelRegistered() - pipeline.fireChannelActive() + pipeline.fireUserEventTriggered(ClientInboundHandler.SendRequest) val frozenToRemove = toRemove.toSet @@ -159,13 +159,15 @@ final case class NettyClientDriver private[netty] ( // If onComplete was already set, it means another fiber is already in the process of fulfilling the promises // so we don't need to fulfill `onResponse` nettyRuntime.unsafeRunSync { - ZIO.whenZIO(onComplete.interrupt)( - onResponse.fail( - new PrematureChannelClosureException( - "Channel closed while executing the request. This is likely caused due to a client connection misconfiguration", + ZIO + .whenZIO(onComplete.interrupt)( + onResponse.fail( + new PrematureChannelClosureException( + "Channel closed while executing the request. This is likely caused due to a client connection misconfiguration", + ), ), - ), - ) + ) + .unit } } } diff --git a/zio-http/jvm/src/main/scala/zio/http/netty/client/NettyConnectionPool.scala b/zio-http/jvm/src/main/scala/zio/http/netty/client/NettyConnectionPool.scala index eb0a6f23a8..e657fe7c01 100644 --- a/zio-http/jvm/src/main/scala/zio/http/netty/client/NettyConnectionPool.scala +++ b/zio-http/jvm/src/main/scala/zio/http/netty/client/NettyConnectionPool.scala @@ -126,6 +126,26 @@ object NettyConnectionPool { } yield ch } + /** + * Refreshes the idle timeout handler on the channel pipeline. + * @return + * true if the handler was successfully refreshed prior to the channel being + * closed + */ + private def refreshIdleTimeoutHandler( + channel: JChannel, + timeout: Duration, + ): Boolean = { + channel + .pipeline() + .replace( + Names.ReadTimeoutHandler, + Names.ReadTimeoutHandler, + new ReadTimeoutHandler(timeout.toMillis, TimeUnit.MILLISECONDS), + ) + channel.isOpen + } + private final class ReadTimeoutErrorHandler(nettyRuntime: NettyRuntime)(implicit trace: Trace) extends ChannelInboundHandlerAdapter { @@ -222,8 +242,10 @@ object NettyConnectionPool { // We retry a few times hoping to obtain an open channel // NOTE: We need to release the channel before retrying, so that it can be closed and removed from the pool // We do that in a forked fiber so that we don't "block" the current fiber while the new resource is obtained - if (channel.isOpen) ZIO.succeed(channel) - else invalidate(channel) *> release.forkDaemon *> ZIO.fail(None) + if (channel.isOpen && idleTimeout.fold(true)(refreshIdleTimeoutHandler(channel, _))) + ZIO.succeed(channel) + else + invalidate(channel) *> release.forkDaemon *> ZIO.fail(None) } .retry(retrySchedule(key)) .catchAll { diff --git a/zio-http/jvm/src/main/scala/zio/http/netty/client/WebSocketClientInboundHandler.scala b/zio-http/jvm/src/main/scala/zio/http/netty/client/WebSocketClientInboundHandler.scala index f674b4934a..29740447e1 100644 --- a/zio-http/jvm/src/main/scala/zio/http/netty/client/WebSocketClientInboundHandler.scala +++ b/zio-http/jvm/src/main/scala/zio/http/netty/client/WebSocketClientInboundHandler.scala @@ -17,11 +17,11 @@ package zio.http.netty.client import zio.stacktracer.TracingImplicits.disableAutoTrace -import zio.{Exit, Promise, Trace, Unsafe} +import zio.{Exit, Promise, Unsafe} import zio.http.Response import zio.http.internal.ChannelState -import zio.http.netty.{NettyResponse, NettyRuntime} +import zio.http.netty.NettyResponse import io.netty.channel.{ChannelHandlerContext, SimpleChannelInboundHandler} import io.netty.handler.codec.http.FullHttpResponse @@ -33,7 +33,7 @@ final class WebSocketClientInboundHandler( implicit private val unsafeClass: Unsafe = Unsafe.unsafe override def channelActive(ctx: ChannelHandlerContext): Unit = - ctx.fireChannelActive() + ctx.fireChannelActive(): Unit override def channelRead0(ctx: ChannelHandlerContext, msg: FullHttpResponse): Unit = { onResponse.unsafe.done(Exit.succeed(NettyResponse(msg))) diff --git a/zio-http/jvm/src/main/scala/zio/http/netty/model/Conversions.scala b/zio-http/jvm/src/main/scala/zio/http/netty/model/Conversions.scala index e0dc8b1604..9ceb2d1a1f 100644 --- a/zio-http/jvm/src/main/scala/zio/http/netty/model/Conversions.scala +++ b/zio-http/jvm/src/main/scala/zio/http/netty/model/Conversions.scala @@ -87,7 +87,7 @@ private[netty] object Conversions { ) private def encodeHeaderListToNetty(headers: Iterable[Header]): HttpHeaders = { - val nettyHeaders = new DefaultHttpHeaders(true) + val nettyHeaders = new DefaultHttpHeaders() val setCookieName = Header.SetCookie.name val iter = headers.iterator while (iter.hasNext) { diff --git a/zio-http/jvm/src/main/scala/zio/http/netty/server/ServerChannelInitializer.scala b/zio-http/jvm/src/main/scala/zio/http/netty/server/ServerChannelInitializer.scala index 31186ad54c..f75eb9c4bf 100644 --- a/zio-http/jvm/src/main/scala/zio/http/netty/server/ServerChannelInitializer.scala +++ b/zio-http/jvm/src/main/scala/zio/http/netty/server/ServerChannelInitializer.scala @@ -60,7 +60,13 @@ private[zio] final case class ServerChannelInitializer( // Instead of ServerCodec, we should use Decoder and Encoder separately to have more granular control over performance. pipeline.addLast( Names.HttpRequestDecoder, - new HttpRequestDecoder(cfg.maxInitialLineLength, cfg.maxHeaderSize, DEFAULT_MAX_CHUNK_SIZE, false), + new HttpRequestDecoder( + new HttpDecoderConfig() + .setMaxInitialLineLength(cfg.maxInitialLineLength) + .setMaxHeaderSize(cfg.maxHeaderSize) + .setMaxChunkSize(DEFAULT_MAX_CHUNK_SIZE) + .setValidateHeaders(false), + ), ) pipeline.addLast(Names.HttpResponseEncoder, new HttpResponseEncoder()) diff --git a/zio-http/jvm/src/main/scala/zio/http/netty/server/ServerInboundHandler.scala b/zio-http/jvm/src/main/scala/zio/http/netty/server/ServerInboundHandler.scala index 10507374fd..8d43c1f88e 100644 --- a/zio-http/jvm/src/main/scala/zio/http/netty/server/ServerInboundHandler.scala +++ b/zio-http/jvm/src/main/scala/zio/http/netty/server/ServerInboundHandler.scala @@ -124,7 +124,7 @@ private[zio] final case class ServerInboundHandler( } cause match { case _: ReadTimeoutException => - ctx.close() + ctx.close(): Unit case _ => super.exceptionCaught(ctx, t) } @@ -168,29 +168,30 @@ private[zio] final case class ServerInboundHandler( runtime: NettyRuntime, response: Response, jRequest: HttpRequest, - ): Option[Task[Unit]] = { + ): Task[Option[Task[Unit]]] = { response.body match { case WebsocketBody(socketApp) if response.status == Status.SwitchingProtocols => - upgradeToWebSocket(ctx, jRequest, socketApp, runtime) - None + upgradeToWebSocket(ctx, jRequest, socketApp, runtime).as(None) case _ => - val jResponse = NettyResponseEncoder.encode(response) + ZIO.attempt { + val jResponse = NettyResponseEncoder.encode(response) - if (!jResponse.isInstanceOf[FullHttpResponse]) { + if (!jResponse.isInstanceOf[FullHttpResponse]) { - // We MUST get the content length from the headers BEFORE we call writeAndFlush otherwise netty will mutate - // the headers and remove `content-length` since there is no content - val contentLength = - jResponse.headers().get(HttpHeaderNames.CONTENT_LENGTH) match { - case null => None - case value => Some(value.toLong) - } + // We MUST get the content length from the headers BEFORE we call writeAndFlush otherwise netty will mutate + // the headers and remove `content-length` since there is no content + val contentLength = + jResponse.headers().get(HttpHeaderNames.CONTENT_LENGTH) match { + case null => None + case value => Some(value.toLong) + } - ctx.writeAndFlush(jResponse) - NettyBodyWriter.writeAndFlush(response.body, contentLength, ctx) - } else { - ctx.writeAndFlush(jResponse) - None + ctx.writeAndFlush(jResponse) + NettyBodyWriter.writeAndFlush(response.body, contentLength, ctx, isResponseCompressible(jRequest)) + } else { + ctx.writeAndFlush(jResponse) + None + } } } } @@ -206,6 +207,16 @@ private[zio] final case class ServerInboundHandler( } } + private def isResponseCompressible(req: HttpRequest): Boolean = { + config.responseCompression match { + case None => false + case Some(cfg) => + val headers = req.headers() + val headerName = Header.AcceptEncoding.name + cfg.options.exists(opt => headers.containsValue(headerName, opt.kind.name, true)) + } + } + private def makeZioRequest(ctx: ChannelHandlerContext, nettyReq: HttpRequest): Request = { val nettyHttpVersion = nettyReq.protocolVersion() val protocolVersion = nettyHttpVersion match { @@ -256,57 +267,57 @@ private[zio] final case class ServerInboundHandler( } - // TODO: reimplement it on server settings level -// private def setServerTime(time: ServerTime, response: Response, jResponse: HttpResponse): Unit = { -// val _ = -// if (response.addServerTime) -// jResponse.headers().set(HttpHeaderNames.DATE, time.refreshAndGet()) -// } - /* * Checks if the response requires to switch protocol to websocket. Returns * true if it can, otherwise returns false */ - @tailrec private def upgradeToWebSocket( ctx: ChannelHandlerContext, jReq: HttpRequest, webSocketApp: WebSocketApp[Any], runtime: NettyRuntime, - ): Unit = { + ): Task[Unit] = { jReq match { case jReq: FullHttpRequest => - val queue = - runtime.unsafeRunSync { - Queue.unbounded[WebSocketChannelEvent].tap { queue => + Queue + .unbounded[WebSocketChannelEvent] + .tap { queue => + ZIO.suspend { val nettyChannel = NettyChannel.make[JWebSocketFrame](ctx.channel()) val webSocketChannel = WebSocketChannel.make(nettyChannel, queue) webSocketApp.handler.runZIO(webSocketChannel).ignoreLogged.forkDaemon } } - ctx - .channel() - .pipeline() - .addLast( - new WebSocketServerProtocolHandler( - NettySocketProtocol.serverBuilder(webSocketApp.customConfig.getOrElse(config.webSocketConfig)).build(), - ), - ) - .addLast(Names.WebSocketHandler, new WebSocketAppHandler(runtime, queue, None)) - - val retained = jReq.retainedDuplicate() - val _ = ctx.channel().eventLoop().submit { () => ctx.fireChannelRead(retained) } - - case jReq: HttpRequest => - val fullRequest = new DefaultFullHttpRequest(jReq.protocolVersion(), jReq.method(), jReq.uri()) - fullRequest.headers().setAll(jReq.headers()) - upgradeToWebSocket(ctx: ChannelHandlerContext, fullRequest, webSocketApp, runtime) + .flatMap { queue => + ZIO.attempt { + ctx + .channel() + .pipeline() + .addLast( + new WebSocketServerProtocolHandler( + NettySocketProtocol + .serverBuilder(webSocketApp.customConfig.getOrElse(config.webSocketConfig)) + .build(), + ), + ) + .addLast(Names.WebSocketHandler, new WebSocketAppHandler(runtime, queue, None)) + + val retained = jReq.retainedDuplicate() + val _ = ctx.channel().eventLoop().submit { () => ctx.fireChannelRead(retained) } + } + } + case jReq: HttpRequest => + ZIO.suspend { + val fullRequest = new DefaultFullHttpRequest(jReq.protocolVersion(), jReq.method(), jReq.uri()) + fullRequest.headers().setAll(jReq.headers()) + upgradeToWebSocket(ctx: ChannelHandlerContext, fullRequest, webSocketApp, runtime) + } } } private def writeNotFound(ctx: ChannelHandlerContext, jReq: HttpRequest): Unit = { val response = Response.notFound(jReq.uri()) - attemptFastWrite(ctx, response) + attemptFastWrite(ctx, response): Unit } private def writeResponse( @@ -328,18 +339,18 @@ private[zio] final case class ServerInboundHandler( }, ) }.flatMap { response => - ZIO.attempt { + ZIO.suspend { if (response ne null) { val done = attemptFastWrite(ctx, response) if (!done) attemptFullWrite(ctx, runtime, response, jReq) else - None + ZIO.none } else { if (ctx.channel().isOpen) { writeNotFound(ctx, jReq) } - None + ZIO.none } }.foldCauseZIO( cause => ZIO.attempt(attemptFastWrite(ctx, withDefaultErrorResponse(cause.squash))), diff --git a/zio-http/jvm/src/test/scala/zio/http/ClientLayerSpec.scala b/zio-http/jvm/src/test/scala/zio/http/ClientLayerSpec.scala index 06eb56be20..cd120502ea 100644 --- a/zio-http/jvm/src/test/scala/zio/http/ClientLayerSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/ClientLayerSpec.scala @@ -2,11 +2,10 @@ package zio.http import java.util.concurrent.TimeUnit -import zio.test.Assertion.{isGreaterThan, isLessThan, isWithin} +import zio.test.Assertion.isWithin import zio.test.{TestAspect, assertZIO} import zio.{Clock, ZIO, ZLayer, durationInt} -import zio.http.Client import zio.http.netty.NettyConfig object ClientLayerSpec extends ZIOHttpSpec { diff --git a/zio-http/jvm/src/test/scala/zio/http/ClientSpec.scala b/zio-http/jvm/src/test/scala/zio/http/ClientSpec.scala index 2b4426f8e8..cdc23e1ece 100644 --- a/zio-http/jvm/src/test/scala/zio/http/ClientSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/ClientSpec.scala @@ -18,6 +18,8 @@ package zio.http import java.net.ConnectException +import scala.annotation.nowarn + import zio._ import zio.test.Assertion._ import zio.test.TestAspect.{sequential, timeout, withLiveClock} @@ -84,7 +86,7 @@ object ClientSpec extends HttpRunnableSpec { .deployAndRequest(c => (c @@ ZClientAspect.requestLogging()).get("/")) .runZIO(()) loggedUrl <- ZTestLogger.logOutput.map(_.collectFirst { case m => m.annotations("url") }.mkString) - } yield assertTrue(loggedUrl == s"$baseURL/") + } yield assertTrue(loggedUrl == s"$baseURL/"): @nowarn }, test("reading of unfinished body must fail") { val app = Handler.fromStreamChunked(ZStream.never).sandbox.toRoutes diff --git a/zio-http/jvm/src/test/scala/zio/http/HandlerSpec.scala b/zio-http/jvm/src/test/scala/zio/http/HandlerSpec.scala index 3180291070..e300f11c65 100644 --- a/zio-http/jvm/src/test/scala/zio/http/HandlerSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/HandlerSpec.scala @@ -18,11 +18,14 @@ package zio.http import java.nio.file.Files +import scala.annotation.nowarn + import zio._ import zio.test.Assertion._ import zio.test.TestAspect.timeout import zio.test._ +@nowarn("msg=dead code") object HandlerSpec extends ZIOHttpSpec with ExitAssertion { def spec = suite("Handler")( diff --git a/zio-http/jvm/src/test/scala/zio/http/RequestStreamingServerSpec.scala b/zio-http/jvm/src/test/scala/zio/http/RequestStreamingServerSpec.scala index ee69261f84..69647acb2a 100644 --- a/zio-http/jvm/src/test/scala/zio/http/RequestStreamingServerSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/RequestStreamingServerSpec.scala @@ -111,7 +111,7 @@ object RequestStreamingServerSpec extends HttpRunnableSpec { suite("app with request streaming") { appWithReqStreaming.as(List(requestBodySpec, streamingServerSpec)) } - }.provideSome[DynamicServer & Server.Config & Server & Client](Scope.default) + }.provideSome[DynamicServer & Server & Client](Scope.default) .provideShared( DynamicServer.live, ZLayer.succeed(configAppWithRequestStreaming), diff --git a/zio-http/jvm/src/test/scala/zio/http/ResponseCompressionSpec.scala b/zio-http/jvm/src/test/scala/zio/http/ResponseCompressionSpec.scala index 058c4bb5b0..c03957ebbe 100644 --- a/zio-http/jvm/src/test/scala/zio/http/ResponseCompressionSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/ResponseCompressionSpec.scala @@ -73,7 +73,12 @@ object ResponseCompressionSpec extends ZIOHttpSpec { ), ) - private val app = text ++ stream + private val file: Routes[Any, Response] = + Routes( + Method.GET / "file" -> Handler.fromResource("TestStatic/TestFile1.txt"), + ).sandbox + + private val app = text ++ stream ++ file private lazy val serverConfig: Server.Config = Server.Config.default.port(0).responseCompression() override def spec = @@ -100,6 +105,22 @@ object ResponseCompressionSpec extends ZIOHttpSpec { test("with Response.stream (chunked)") { streamTest("stream-chunked") }, + test("with files") { + for { + server <- ZIO.service[Server] + client <- ZIO.service[Client] + _ <- server.install(app) + response <- client.request( + Request( + method = Method.GET, + url = URL(Path.root / "file", kind = URL.Location.Absolute(Scheme.HTTP, "localhost", Some(server.port))), + ) + .addHeader(Header.AcceptEncoding(Header.AcceptEncoding.GZip(), Header.AcceptEncoding.Deflate())), + ) + res <- response.body.asChunk + decompressed <- decompressed(res) + } yield assertTrue(decompressed == "This file is added for testing Static File Server.") + }, ).provide( ZLayer.succeed(serverConfig), Server.customized, diff --git a/zio-http/jvm/src/test/scala/zio/http/RoutesMiddlewareSpec.scala b/zio-http/jvm/src/test/scala/zio/http/RoutesMiddlewareSpec.scala index 04aaac657b..32696fd165 100644 --- a/zio-http/jvm/src/test/scala/zio/http/RoutesMiddlewareSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/RoutesMiddlewareSpec.scala @@ -20,8 +20,6 @@ import zio._ import zio.test.Assertion._ import zio.test._ -import zio.http.Method - object RoutesMiddlewareSpec extends ZIOHttpSpec with ExitAssertion { def spec: Spec[Any, Any] = diff --git a/zio-http/jvm/src/test/scala/zio/http/ServerSpec.scala b/zio-http/jvm/src/test/scala/zio/http/ServerSpec.scala index 1dc82b8d11..5fde09033a 100644 --- a/zio-http/jvm/src/test/scala/zio/http/ServerSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/ServerSpec.scala @@ -498,7 +498,7 @@ object ServerSpec extends HttpRunnableSpec { suite("ServerSpec") { val spec = dynamicAppSpec + responseSpec + requestSpec + requestBodySpec + serverErrorSpec suite("app without request streaming") { ZIO.scoped(app.as(List(spec))) } - }.provideSome[DynamicServer & Server.Config & Server & Client](Scope.default) + }.provideSome[DynamicServer & Server & Client](Scope.default) .provideShared( DynamicServer.live, ZLayer.succeed(configApp), diff --git a/zio-http/jvm/src/test/scala/zio/http/StaticServerSpec.scala b/zio-http/jvm/src/test/scala/zio/http/StaticServerSpec.scala index 9a6d1eb62d..86d7387872 100644 --- a/zio-http/jvm/src/test/scala/zio/http/StaticServerSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/StaticServerSpec.scala @@ -101,7 +101,7 @@ object StaticServerSpec extends HttpRunnableSpec { .as( List(staticAppSpec, nonZIOSpec, throwableAppSpec, multiHeadersSpec), ) - }.provideSome[DynamicServer & Server.Config & Server & Client](Scope.default) + }.provideSome[DynamicServer & Server & Client](Scope.default) .provideShared( DynamicServer.live, serverTestLayer, diff --git a/zio-http/jvm/src/test/scala/zio/http/WebSocketConfig.scala b/zio-http/jvm/src/test/scala/zio/http/WebSocketConfig.scala index 7c7936b287..09d0b177bf 100644 --- a/zio-http/jvm/src/test/scala/zio/http/WebSocketConfig.scala +++ b/zio-http/jvm/src/test/scala/zio/http/WebSocketConfig.scala @@ -18,13 +18,11 @@ package zio.http import zio._ import zio.test.TestAspect._ -import zio.test.{TestClock, assertCompletes, assertTrue, assertZIO, testClock} +import zio.test.assertTrue -import zio.http.ChannelEvent.{Read, Unregistered, UserEvent, UserEventTriggered} +import zio.http.ChannelEvent.{Read, UserEvent, UserEventTriggered} import zio.http.internal.{DynamicServer, HttpRunnableSpec, serverTestLayer} import zio.http.netty.NettyConfig -import zio.http.{Client, DnsResolver} -// import zio.http.netty.NettyConfig object WebSocketConfigSpec extends HttpRunnableSpec { diff --git a/zio-http/jvm/src/test/scala/zio/http/WebSocketSpec.scala b/zio-http/jvm/src/test/scala/zio/http/WebSocketSpec.scala index 2df18f2628..197bce56ee 100644 --- a/zio-http/jvm/src/test/scala/zio/http/WebSocketSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/WebSocketSpec.scala @@ -35,9 +35,9 @@ object WebSocketSpec extends HttpRunnableSpec { id <- DynamicServer.deploy { Handler.webSocket { channel => channel.receiveAll { - case event @ Read(frame) => channel.send(Read(frame)) *> msg.add(event) - case event @ Unregistered => msg.add(event, true) - case event => msg.add(event) + case event @ Read(frame) => channel.send(Read(frame)) *> msg.add(event) + case event: Unregistered.type => msg.add(event, isDone = true) + case event => msg.add(event) } }.toRoutes } @@ -126,9 +126,9 @@ object WebSocketSpec extends HttpRunnableSpec { id <- DynamicServer.deploy { Handler.webSocket { channel => channel.receiveAll { - case event @ Read(frame) => channel.send(Read(frame)) *> msg.add(event) - case event @ Unregistered => msg.add(event, true) - case event => msg.add(event) + case event @ Read(frame) => channel.send(Read(frame)) *> msg.add(event) + case event: Unregistered.type => msg.add(event, isDone = true) + case event => msg.add(event) } }.toRoutes } diff --git a/zio-http/jvm/src/test/scala/zio/http/ZClientAspectSpec.scala b/zio-http/jvm/src/test/scala/zio/http/ZClientAspectSpec.scala index 88f7da5c8b..0e7c12fc42 100644 --- a/zio-http/jvm/src/test/scala/zio/http/ZClientAspectSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/ZClientAspectSpec.scala @@ -16,6 +16,8 @@ package zio.http +import scala.annotation.nowarn + import zio._ import zio.test.TestAspect.withLiveClock import zio.test._ @@ -32,6 +34,7 @@ object ZClientAspectSpec extends ZIOHttpSpec { val redir: Routes[Any, Response] = Route.handled(Method.GET / "redirect")(Handler.fromResponse(Response.redirect(URL.empty / "hello"))).toRoutes + @nowarn("msg=possible missing interpolator") override def spec: Spec[TestEnvironment with Scope, Any] = suite("ZClientAspect")( test("debug") { diff --git a/zio-http/jvm/src/test/scala/zio/http/endpoint/CustomErrorSpec.scala b/zio-http/jvm/src/test/scala/zio/http/endpoint/CustomErrorSpec.scala index 3f096d8a96..0b59d3a610 100644 --- a/zio-http/jvm/src/test/scala/zio/http/endpoint/CustomErrorSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/endpoint/CustomErrorSpec.scala @@ -16,6 +16,8 @@ package zio.http.endpoint +import scala.annotation.nowarn + import zio._ import zio.test._ @@ -28,6 +30,7 @@ import zio.http._ import zio.http.codec._ import zio.http.endpoint.EndpointSpec.extractStatus +@nowarn("msg=possible missing interpolator") object CustomErrorSpec extends ZIOHttpSpec { def spec = suite("CustomErrorSpec")( test("simple custom error response") { diff --git a/zio-http/jvm/src/test/scala/zio/http/endpoint/ExamplesSpec.scala b/zio-http/jvm/src/test/scala/zio/http/endpoint/ExamplesSpec.scala index 3374831d2c..7551ed3d7d 100644 --- a/zio-http/jvm/src/test/scala/zio/http/endpoint/ExamplesSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/endpoint/ExamplesSpec.scala @@ -47,10 +47,10 @@ object ExamplesSpec extends ZIOHttpSpec { Endpoint(GET / "repos" / string("org") / string("repo")) .out[String] .examplesIn( - "org/repo1" -> ("zio", "http"), - "org/repo2" -> ("zio", "zio"), - "org/repo3" -> ("zio", repo1), - "org/repo4" -> ("zio", repo2), + ("org/repo1", ("zio", "http")), + ("org/repo2", ("zio", "zio")), + ("org/repo3", ("zio", repo1)), + ("org/repo4", ("zio", repo2)), ) .examplesOut("repos" -> s"zio, http, $repo1, $repo2") val inExamples1 = endpoint.examplesIn @@ -59,10 +59,10 @@ object ExamplesSpec extends ZIOHttpSpec { val expectedOutExamples1 = Map("repos" -> s"all, zio, repos, $repo1, $repo2") val inExamples2 = endpoint2.examplesIn val expectedInExamples2 = Map( - "org/repo1" -> ("zio", "http"), - "org/repo2" -> ("zio", "zio"), - "org/repo3" -> ("zio", repo1), - "org/repo4" -> ("zio", repo2), + ("org/repo1", ("zio", "http")), + ("org/repo2", ("zio", "zio")), + ("org/repo3", ("zio", repo1)), + ("org/repo4", ("zio", repo2)), ) val outExamples2 = endpoint2.examplesOut val expectedOutExamples2 = Map("repos" -> s"zio, http, $repo1, $repo2") diff --git a/zio-http/jvm/src/test/scala/zio/http/endpoint/MultipartSpec.scala b/zio-http/jvm/src/test/scala/zio/http/endpoint/MultipartSpec.scala index e8d390e9b9..128eb4685d 100644 --- a/zio-http/jvm/src/test/scala/zio/http/endpoint/MultipartSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/endpoint/MultipartSpec.scala @@ -16,6 +16,8 @@ package zio.http.endpoint +import scala.annotation.nowarn + import zio._ import zio.test._ @@ -27,6 +29,8 @@ import zio.http.codec._ import zio.http.endpoint.EndpointSpec.ImageMetadata import zio.http.forms.Fixtures.formField +@nowarn("msg=possible missing interpolator") +@nowarn("msg=dead code") object MultipartSpec extends ZIOHttpSpec { def spec = suite("MultipartSpec")( suite("multipart/form-data")( diff --git a/zio-http/jvm/src/test/scala/zio/http/endpoint/RequestSpec.scala b/zio-http/jvm/src/test/scala/zio/http/endpoint/RequestSpec.scala index a5531366b2..12af7bba14 100644 --- a/zio-http/jvm/src/test/scala/zio/http/endpoint/RequestSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/endpoint/RequestSpec.scala @@ -16,6 +16,8 @@ package zio.http.endpoint +import scala.annotation.nowarn + import zio._ import zio.test._ @@ -30,6 +32,8 @@ import zio.http.codec.HttpCodec.{query, queryInt} import zio.http.codec._ import zio.http.endpoint.EndpointSpec.{extractStatus, testEndpoint, testEndpointWithHeaders} +@nowarn("msg=possible missing interpolator") +@nowarn("msg=dead code") object RequestSpec extends ZIOHttpSpec { def spec = suite("RequestSpec")( suite("handler")( diff --git a/zio-http/jvm/src/test/scala/zio/http/endpoint/RoundtripSpec.scala b/zio-http/jvm/src/test/scala/zio/http/endpoint/RoundtripSpec.scala index ba29734388..d22d583cc1 100644 --- a/zio-http/jvm/src/test/scala/zio/http/endpoint/RoundtripSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/endpoint/RoundtripSpec.scala @@ -16,6 +16,8 @@ package zio.http.endpoint +import scala.annotation.nowarn + import zio._ import zio.test.Assertion._ import zio.test.TestAspect._ @@ -242,6 +244,7 @@ object RoundtripSpec extends ZIOHttpSpec { .outError[String](Status.BadRequest) .out[String] ?? Doc.p("doc") + @nowarn("msg=dead code") val handler = api.implement { Handler.fromFunction { case (accountId, name, instanceName, args, env) => throw new RuntimeException("I can't code") diff --git a/zio-http/jvm/src/test/scala/zio/http/endpoint/openapi/OpenAPIGenSpec.scala b/zio-http/jvm/src/test/scala/zio/http/endpoint/openapi/OpenAPIGenSpec.scala index 3463b33c8e..9b037371b2 100644 --- a/zio-http/jvm/src/test/scala/zio/http/endpoint/openapi/OpenAPIGenSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/endpoint/openapi/OpenAPIGenSpec.scala @@ -2232,7 +2232,7 @@ object OpenAPIGenSpec extends ZIOSpecDefault { Endpoint(Method.GET / "root" / string("name")) .in[Payload] .out[String] - .examplesIn("hi" -> ("name_value", Payload("input"))) + .examplesIn(("hi", ("name_value", Payload("input")))) val openApi = OpenAPIGen.fromEndpoints( @@ -2333,7 +2333,7 @@ object OpenAPIGenSpec extends ZIOSpecDefault { Endpoint(Method.GET / "root" / string("name")) .inCodec(ContentCodec.content[Payload] | ContentCodec.content[String]) .out[String] - .examplesIn("hi" -> ("name_value", Left(Payload("input"))), "ho" -> ("name_value2", Right("input"))) + .examplesIn(("hi", ("name_value", Left(Payload("input")))), ("ho", ("name_value2", Right("input")))) val openApi = OpenAPIGen.fromEndpoints( title = "Alternated input examples", diff --git a/zio-http/jvm/src/test/scala/zio/http/forms/Fixtures.scala b/zio-http/jvm/src/test/scala/zio/http/forms/Fixtures.scala index 0c8de402ea..8fa46606b4 100644 --- a/zio-http/jvm/src/test/scala/zio/http/forms/Fixtures.scala +++ b/zio-http/jvm/src/test/scala/zio/http/forms/Fixtures.scala @@ -108,7 +108,7 @@ object Fixtures { Gen.const(StandardType.IntType), Gen.const(StandardType.UUIDType), ) - value <- standardType match { + value <- (standardType: @unchecked) match { case StandardType.StringType => Gen.string case StandardType.BoolType => Gen.boolean case StandardType.IntType => Gen.int diff --git a/zio-http/jvm/src/test/scala/zio/http/headers/ContentTypeSpec.scala b/zio-http/jvm/src/test/scala/zio/http/headers/ContentTypeSpec.scala index 5093b4b0fd..5dda74c83d 100644 --- a/zio-http/jvm/src/test/scala/zio/http/headers/ContentTypeSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/headers/ContentTypeSpec.scala @@ -16,6 +16,8 @@ package zio.http.headers +import scala.annotation.nowarn + import zio.test._ import zio.http.Header.ContentType @@ -23,6 +25,7 @@ import zio.http.{MediaType, ZIOHttpSpec} object ContentTypeSpec extends ZIOHttpSpec { + @nowarn("msg=possible missing interpolator") override def spec = suite("ContentType header suite")( test("parsing of invalid ContentType values") { assertTrue( diff --git a/zio-http/jvm/src/test/scala/zio/http/headers/HostSpec.scala b/zio-http/jvm/src/test/scala/zio/http/headers/HostSpec.scala index 8ad8f2931b..b9519905cc 100644 --- a/zio-http/jvm/src/test/scala/zio/http/headers/HostSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/headers/HostSpec.scala @@ -16,6 +16,8 @@ package zio.http.headers +import scala.annotation.nowarn + import zio.Scope import zio.test._ @@ -23,6 +25,7 @@ import zio.http.Header.Host import zio.http.ZIOHttpSpec import zio.http.internal.HttpGen +@nowarn("msg=possible missing interpolator") object HostSpec extends ZIOHttpSpec { override def spec: Spec[TestEnvironment with Scope, Any] = suite("Host header suite")( diff --git a/zio-http/jvm/src/test/scala/zio/http/headers/ProxyAuthenticateSpec.scala b/zio-http/jvm/src/test/scala/zio/http/headers/ProxyAuthenticateSpec.scala index 0ce28f99cf..5ca90bff4a 100644 --- a/zio-http/jvm/src/test/scala/zio/http/headers/ProxyAuthenticateSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/headers/ProxyAuthenticateSpec.scala @@ -16,6 +16,8 @@ package zio.http.headers +import scala.annotation.nowarn + import zio.Scope import zio.test._ @@ -23,6 +25,7 @@ import zio.http.Header.ProxyAuthenticate import zio.http.ZIOHttpSpec import zio.http.internal.HttpGen +@nowarn("msg=possible missing interpolator") object ProxyAuthenticateSpec extends ZIOHttpSpec { override def spec: Spec[TestEnvironment with Scope, Nothing] = suite("ProxyAuthenticateSpec")( diff --git a/zio-http/jvm/src/test/scala/zio/http/netty/NettyStreamBodySpec.scala b/zio-http/jvm/src/test/scala/zio/http/netty/NettyStreamBodySpec.scala index af011ee769..ad4acef187 100644 --- a/zio-http/jvm/src/test/scala/zio/http/netty/NettyStreamBodySpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/netty/NettyStreamBodySpec.scala @@ -69,7 +69,7 @@ object NettyStreamBodySpec extends HttpRunnableSpec { ZStream.fromQueue(firstResponseQueue) @@ ZStreamAspect.rechunk(message.length / 3), ZStream.fromIterable(message.getBytes), ).iterator, - message.length, + message.length.toLong, ) client <- ZIO.service[Client] firstResponse <- makeRequest(client, port) diff --git a/zio-http/jvm/src/test/scala/zio/http/netty/client/NettyConnectionPoolSpec.scala b/zio-http/jvm/src/test/scala/zio/http/netty/client/NettyConnectionPoolSpec.scala index f670c4b722..b7fe1b575a 100644 --- a/zio-http/jvm/src/test/scala/zio/http/netty/client/NettyConnectionPoolSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/netty/client/NettyConnectionPoolSpec.scala @@ -168,7 +168,7 @@ object NettyConnectionPoolSpec extends HttpRunnableSpec { }, ) - private def connectionPoolTimeoutTest = + private def connectionPoolTimeoutTest = { test("client connection timeouts while in connection pool") { def executeRequest(idx: Int) = app @@ -199,6 +199,25 @@ object NettyConnectionPoolSpec extends HttpRunnableSpec { testNettyServerConfig, Server.customized, ) @@ withLiveClock + } + test("idle timeout is refreshed on each request") { + val f = Handler + .fromZIO(ZIO.succeed(Response.text("ok")).delay(150.millis)) + .toRoutes + .deploy(Request()) + .map(_.status) + .map(assert(_)(equalTo(Status.Ok))) + + ZIO.collectAll(List.fill(4)(f)).map(_.foldLeft(assertCompletes)(_ && _)) + }.provideSome[Scope]( + ZLayer(appKeepAliveEnabled.unit), + DynamicServer.live, + ZLayer.succeed(Server.Config.default.idleTimeout(500.millis).onAnyOpenPort), + testNettyServerConfig, + Server.customized, + Client.live, + ZLayer.succeed(Client.Config.default.idleTimeout(500.millis)), + DnsResolver.default, + ) @@ withLiveClock private def connectionPoolShutdownSpec = test("connections are closed when pool is closed") { diff --git a/zio-http/jvm/src/test/scala/zio/http/netty/model/ConversionsSpec.scala b/zio-http/jvm/src/test/scala/zio/http/netty/model/ConversionsSpec.scala index 5e1cbf9d12..978baa6dc4 100644 --- a/zio-http/jvm/src/test/scala/zio/http/netty/model/ConversionsSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/netty/model/ConversionsSpec.scala @@ -16,6 +16,8 @@ package zio.http.netty.model +import scala.annotation.nowarn + import zio.Scope import zio.test._ @@ -24,6 +26,7 @@ import zio.http.{Header, Headers, Version, ZIOHttpSpec} import io.netty.handler.codec.http.websocketx.WebSocketScheme import io.netty.handler.codec.http.{DefaultHttpHeaders, HttpHeaders, HttpScheme, HttpVersion} +@nowarn("msg=possible missing interpolator") object ConversionsSpec extends ZIOHttpSpec { override def spec: Spec[TestEnvironment with Scope, Any] = suite("Netty conversions")( @@ -42,7 +45,7 @@ object ConversionsSpec extends ZIOHttpSpec { test("header with multiple values should not be escaped") { val headers = Headers("Access-Control-Allow-Methods", "POST, GET, OPTIONS") val expected: HttpHeaders = - new DefaultHttpHeaders(true).add("Access-Control-Allow-Methods", "POST, GET, OPTIONS") + new DefaultHttpHeaders().add("Access-Control-Allow-Methods", "POST, GET, OPTIONS") assertTrue(Conversions.headersToNetty(headers) == expected) }, ), diff --git a/zio-http/jvm/src/test/scala/zio/http/template/DomSpec.scala b/zio-http/jvm/src/test/scala/zio/http/template/DomSpec.scala index 39e173480b..cabccc3749 100644 --- a/zio-http/jvm/src/test/scala/zio/http/template/DomSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/template/DomSpec.scala @@ -16,11 +16,14 @@ package zio.http.template +import scala.annotation.nowarn + import zio.test.{assertTrue, check, checkAll} import zio.http.ZIOHttpSpec import zio.http.template.HtmlGen.{tagGen, voidTagGen} +@nowarn("msg=possible missing interpolator") object DomSpec extends ZIOHttpSpec { def spec = suite("DomSpec")( test("empty") { diff --git a/zio-http/shared/src/main/scala/zio/http/DnsResolver.scala b/zio-http/shared/src/main/scala/zio/http/DnsResolver.scala index ce89fed555..240e4a98a0 100644 --- a/zio-http/shared/src/main/scala/zio/http/DnsResolver.scala +++ b/zio-http/shared/src/main/scala/zio/http/DnsResolver.scala @@ -213,7 +213,7 @@ object DnsResolver { refreshRate: Duration, )(implicit trace: Trace): ZIO[Scope, Nothing, DnsResolver] = for { - semaphore <- Semaphore.make(maxConcurrentResolutions) + semaphore <- Semaphore.make(maxConcurrentResolutions.toLong) entries <- Ref.make(Map.empty[String, CacheEntry]) cachingResolver = new CachingResolver(resolver, ttl, unknownHostTtl, maxCount, expireAction, semaphore, entries) _ <- cachingResolver.refreshAndCleanup().scheduleFork(Schedule.fixed(refreshRate)) diff --git a/zio-http/shared/src/main/scala/zio/http/Flash.scala b/zio-http/shared/src/main/scala/zio/http/Flash.scala index 57224e607a..d31c169130 100644 --- a/zio-http/shared/src/main/scala/zio/http/Flash.scala +++ b/zio-http/shared/src/main/scala/zio/http/Flash.scala @@ -367,7 +367,7 @@ object Flash { .flatMap(in => run(flash, in)) private[http] def run[A](flash: Flash[A], sourceMap: Map[String, String]): Either[Throwable, A] = { - def loop[A](flash: Flash[A], map: Map[String, String]): Either[Throwable, A] = + def loop[A0](flash: Flash[A0], map: Map[String, String]): Either[Throwable, A0] = flash match { case Get(schema, key) => map @@ -382,12 +382,12 @@ object Flash { case OrElse(self, that) => loop(self, map) match { case Left(_) => loop(that, map) - case r @ Right(_) => r.asInstanceOf[Either[Throwable, A]] + case r @ Right(_) => r.asInstanceOf[Either[Throwable, A0]] } case FlatMap(self, f) => loop(self, map) match { case Right(value) => loop(f(value), map) - case l @ Left(_) => l.asInstanceOf[Either[Throwable, A]] + case l @ Left(_) => l.asInstanceOf[Either[Throwable, A0]] } case Succeed(a) => Right(a) case Fail(message) => Left(new RuntimeException(message)) diff --git a/zio-http/shared/src/main/scala/zio/http/Handler.scala b/zio-http/shared/src/main/scala/zio/http/Handler.scala index 8dbde524c8..a88e7552cc 100644 --- a/zio-http/shared/src/main/scala/zio/http/Handler.scala +++ b/zio-http/shared/src/main/scala/zio/http/Handler.scala @@ -608,7 +608,7 @@ sealed trait Handler[-R, +Err, -In, +Out] { self => * the handler has been appropriately sandboxed, turning all possible failures * into well-formed HTTP responses. */ - @deprecated("Use toRoutes instead. Will be removed in the next release.") + @deprecated("Use toRoutes instead. Will be removed in the next release.", "3.0.0-RC7") def toHttpApp(implicit err: Err <:< Response, in: Request <:< In, out: Out <:< Response, trace: Trace): HttpApp[R] = { val handler: Handler[R, Response, Request, Response] = self.asInstanceOf[Handler[R, Response, Request, Response]] diff --git a/zio-http/shared/src/main/scala/zio/http/HandlerAspect.scala b/zio-http/shared/src/main/scala/zio/http/HandlerAspect.scala index 2628a0c515..fa96fa29e5 100644 --- a/zio-http/shared/src/main/scala/zio/http/HandlerAspect.scala +++ b/zio-http/shared/src/main/scala/zio/http/HandlerAspect.scala @@ -16,7 +16,6 @@ package zio.http -import java.io.{PrintWriter, StringWriter} import java.nio.charset._ import zio._ @@ -341,7 +340,7 @@ private[http] trait HandlerAspects extends zio.http.internal.HeaderModifier[Hand ): HandlerAspect[Any, Unit] = HandlerAspect.interceptIncomingHandler[Any, Unit] { Handler.fromFunctionExit[Request] { request => - if (verify(request)) Exit.succeed(request -> ()) + if (verify(request)) Exit.succeed((request, ())) else Exit.fail(Response.status(responseStatus).addHeaders(responseHeaders)) } } @@ -447,7 +446,7 @@ private[http] trait HandlerAspects extends zio.http.internal.HeaderModifier[Hand * The identity middleware, which has no effect on request or response. */ val identity: HandlerAspect[Any, Unit] = - interceptHandler[Any, Unit](Handler.identity[Request].map(_ -> ()))(Handler.identity) + interceptHandler[Any, Unit](Handler.identity[Request].map((_, ())))(Handler.identity) /** * Creates conditional middleware that switches between one middleware and @@ -565,7 +564,7 @@ private[http] trait HandlerAspects extends zio.http.internal.HeaderModifier[Hand def interceptOutgoingHandler[Env]( handler: Handler[Env, Nothing, Response, Response], ): HandlerAspect[Env, Unit] = - interceptHandler[Env, Unit](Handler.identity[Request].map(_ -> ()))(handler) + interceptHandler[Env, Unit](Handler.identity[Request].map((_, ())))(handler) /** * Creates a new middleware using transformation functions @@ -794,7 +793,7 @@ private[http] trait HandlerAspects extends zio.http.internal.HeaderModifier[Hand f: Response => Response, ): HandlerAspect[Any, Unit] = HandlerAspect( - ProtocolStack.interceptHandler(Handler.identity[Request].map(_ -> ()))(Handler.fromFunctionZIO[Response] { + ProtocolStack.interceptHandler(Handler.identity[Request].map((_, ())))(Handler.fromFunctionZIO[Response] { response => if (condition(response)) ZIO.succeed(f(response)) else ZIO.succeed(response) }), @@ -809,7 +808,7 @@ private[http] trait HandlerAspects extends zio.http.internal.HeaderModifier[Hand ): HandlerAspect[Env, Unit] = HandlerAspect( ProtocolStack.interceptHandler[Env, Request, (Request, Unit), Response, Response]( - Handler.identity[Request].map(_ -> ()), + Handler.identity[Request].map((_, ())), )(Handler.fromFunctionZIO[Response] { response => condition(response) .flatMap[Env, Response, Response](bool => if (bool) f(response) else ZIO.succeed(response)) diff --git a/zio-http/shared/src/main/scala/zio/http/Header.scala b/zio-http/shared/src/main/scala/zio/http/Header.scala index 9cf6e965a8..858d456ae3 100644 --- a/zio-http/shared/src/main/scala/zio/http/Header.scala +++ b/zio-http/shared/src/main/scala/zio/http/Header.scala @@ -17,7 +17,7 @@ package zio.http import java.net.URI -import java.nio.charset.{Charset, StandardCharsets, UnsupportedCharsetException} +import java.nio.charset.{Charset, UnsupportedCharsetException} import java.time.ZonedDateTime import java.util.Base64 diff --git a/zio-http/shared/src/main/scala/zio/http/HttpApp.scala b/zio-http/shared/src/main/scala/zio/http/HttpApp.scala index f98139e6d2..e2b97f858c 100644 --- a/zio-http/shared/src/main/scala/zio/http/HttpApp.scala +++ b/zio-http/shared/src/main/scala/zio/http/HttpApp.scala @@ -26,7 +26,7 @@ import zio.stacktracer.TracingImplicits.disableAutoTrace * HTTP applications can be installed into a [[zio.http.Server]], which is * capable of using them to serve requests. */ -@deprecated("Use Routes instead. Will be removed in the next release.") +@deprecated("Use Routes instead. Will be removed in the next release.", "3.0.0-RC7") final case class HttpApp[-Env](routes: Routes[Env, Response]) extends PartialFunction[Request, ZIO[Env, Response, Response]] { self => private var _tree: HttpApp.Tree[_] = null.asInstanceOf[HttpApp.Tree[_]] @@ -129,7 +129,7 @@ object HttpApp { /** * An HTTP application that does not handle any routes. */ - @deprecated("Use Routes.empty instead. Will be removed in the next release.") + @deprecated("Use Routes.empty instead. Will be removed in the next release.", "3.0.0-RC7") val empty: HttpApp[Any] = HttpApp(Routes.empty) private[http] final case class Tree[-Env](tree: RoutePattern.Tree[RequestHandler[Env, Response]]) { self => diff --git a/zio-http/shared/src/main/scala/zio/http/Middleware.scala b/zio-http/shared/src/main/scala/zio/http/Middleware.scala index a84f7b8644..3a359ede6b 100644 --- a/zio-http/shared/src/main/scala/zio/http/Middleware.scala +++ b/zio-http/shared/src/main/scala/zio/http/Middleware.scala @@ -17,12 +17,14 @@ package zio.http import java.io.File +import scala.annotation.nowarn + import zio._ import zio.metrics._ import zio.http.codec.{PathCodec, SegmentCodec} -import zio.http.endpoint.EndpointMiddleware.None.Err +@nowarn("msg=shadows type") trait Middleware[-UpperEnv] { self => def apply[Env1 <: UpperEnv, Err](app: Routes[Env1, Err]): Routes[Env1, Err] @@ -42,6 +44,8 @@ trait Middleware[-UpperEnv] { self => self(that(routes)) } } + +@nowarn("msg=shadows type") object Middleware extends HandlerAspects { /** @@ -122,12 +126,12 @@ object Middleware extends HandlerAspects { case Some(origin) => config.allowedOrigin(origin) match { case Some(allowOrigin) if config.allowedMethods.contains(request.method) => - corsHeaders(allowOrigin, acrhHeader, isPreflight = false) -> (request, ()) + (corsHeaders(allowOrigin, acrhHeader, isPreflight = false), (request, ())) case _ => - Headers.empty -> (request, ()) + (Headers.empty, (request, ())) } - case None => Headers.empty -> (request, ()) + case None => (Headers.empty, (request, ())) } }, )(Handler.fromFunction[(Headers, Response)] { case (headers, response) => diff --git a/zio-http/shared/src/main/scala/zio/http/ProtocolStack.scala b/zio-http/shared/src/main/scala/zio/http/ProtocolStack.scala index d539248775..715a756827 100644 --- a/zio-http/shared/src/main/scala/zio/http/ProtocolStack.scala +++ b/zio-http/shared/src/main/scala/zio/http/ProtocolStack.scala @@ -16,6 +16,8 @@ package zio.http +import scala.annotation.nowarn + import zio._ import zio.stacktracer.TracingImplicits.disableAutoTrace @@ -105,7 +107,9 @@ sealed trait ProtocolStack[-Env, -IncomingIn, +IncomingOut, -OutgoingIn, +Outgoi ): ProtocolStack[Env1, IncomingIn, MiddleIncoming, MiddleOutgoing, OutgoingOut] = Concat(self, that) } -object ProtocolStack { + +@nowarn("msg=shadows") +object ProtocolStack { def cond[IncomingIn](predicate: IncomingIn => Boolean): CondBuilder[IncomingIn] = new CondBuilder(predicate) def condZIO[IncomingIn]: CondZIOBuilder[IncomingIn] = new CondZIOBuilder[IncomingIn](()) @@ -200,7 +204,7 @@ object ProtocolStack def incoming(in: IncomingIn)(implicit trace: Trace): ZIO[Env, OutgoingOut, (State, IncomingOut)] = incoming0(in) def outgoing(state: State, in: OutgoingIn)(implicit trace: Trace): ZIO[Env, Nothing, OutgoingOut] = - outgoing0(state, in) + outgoing0((state, in)) } private[http] final case class Cond[Env, IncomingIn, IncomingOut, OutgoingIn, OutgoingOut]( predicate: IncomingIn => Boolean, diff --git a/zio-http/shared/src/main/scala/zio/http/QueryParamsError.scala b/zio-http/shared/src/main/scala/zio/http/QueryParamsError.scala index c74e02bdce..eed44d6265 100644 --- a/zio-http/shared/src/main/scala/zio/http/QueryParamsError.scala +++ b/zio-http/shared/src/main/scala/zio/http/QueryParamsError.scala @@ -16,14 +16,11 @@ package zio.http -import java.nio.charset.Charset - import scala.util.control.NoStackTrace -import zio.{Chunk, NonEmptyChunk} +import zio.NonEmptyChunk import zio.http.codec.TextCodec -import zio.http.internal.QueryParamEncoding sealed trait QueryParamsError extends Exception with NoStackTrace { override def getMessage(): String = message diff --git a/zio-http/shared/src/main/scala/zio/http/Route.scala b/zio-http/shared/src/main/scala/zio/http/Route.scala index fc25ba3c95..b47c28fc16 100644 --- a/zio-http/shared/src/main/scala/zio/http/Route.scala +++ b/zio-http/shared/src/main/scala/zio/http/Route.scala @@ -296,7 +296,7 @@ sealed trait Route[-Env, +Err] { self => def toHandler(implicit ev: Err <:< Response, trace: Trace): Handler[Env, Response, Request, Response] - @deprecated("Use toRoutes instead") + @deprecated("Use toRoutes instead", "3.0.0-RC7") final def toHttpApp(implicit ev: Err <:< Response): HttpApp[Env] = toHandler.toHttpApp final def toRoutes: Routes[Env, Err] = Routes(self) diff --git a/zio-http/shared/src/main/scala/zio/http/Routes.scala b/zio-http/shared/src/main/scala/zio/http/Routes.scala index 815e443eb2..4fbde164da 100644 --- a/zio-http/shared/src/main/scala/zio/http/Routes.scala +++ b/zio-http/shared/src/main/scala/zio/http/Routes.scala @@ -166,7 +166,7 @@ final case class Routes[-Env, +Err](routes: Chunk[zio.http.Route[Env, Err]]) { s def run(request: Request)(implicit trace: Trace): ZIO[Env, Either[Err, Response], Response] = { - class RouteFailure[+Err](val err: Cause[Err]) extends Throwable(null, null, true, false) { + class RouteFailure[+Err0](val err: Cause[Err0]) extends Throwable(null, null, true, false) { override def getMessage: String = err.unified.headOption.fold("")(_.message) override def getStackTrace(): Array[StackTraceElement] = diff --git a/zio-http/shared/src/main/scala/zio/http/Server.scala b/zio-http/shared/src/main/scala/zio/http/Server.scala index 414158b0d2..00ed14acd0 100644 --- a/zio-http/shared/src/main/scala/zio/http/Server.scala +++ b/zio-http/shared/src/main/scala/zio/http/Server.scala @@ -33,7 +33,7 @@ trait Server { /** * Installs the given HTTP application into the server. */ - @deprecated("Install Routes instead. Will be removed in the next release.") + @deprecated("Install Routes instead. Will be removed in the next release.", "3.0.0-RC7") def install[R](httpApp: HttpApp[R])(implicit trace: Trace, tag: EnvironmentTag[R]): URIO[R, Unit] = install(httpApp.routes) @@ -289,11 +289,13 @@ object Server extends ServerPlatformSpecific { def deflate(level: Int = DefaultLevel, bits: Int = DefaultBits, mem: Int = DefaultMem): CompressionOptions = CompressionOptions(level, bits, mem, CompressionType.Deflate) - sealed trait CompressionType + sealed trait CompressionType { + val name: String + } private[http] object CompressionType { - case object GZip extends CompressionType - case object Deflate extends CompressionType + case object GZip extends CompressionType { val name = "gzip" } + case object Deflate extends CompressionType { val name = "deflate" } lazy val config: zio.Config[CompressionType] = zio.Config.string.mapOrFail { @@ -336,7 +338,7 @@ object Server extends ServerPlatformSpecific { } } - @deprecated("Serve Routes instead. Will be removed in the next release.") + @deprecated("Serve Routes instead. Will be removed in the next release.", "3.0.0-RC7") def serve[R]( httpApp: HttpApp[R], )(implicit trace: Trace, tag: EnvironmentTag[R]): URIO[R with Server, Nothing] = { @@ -346,9 +348,9 @@ object Server extends ServerPlatformSpecific { ZIO.never } - @deprecated("Install Routes instead. Will be removed in the next release.") + @deprecated("Install Routes instead. Will be removed in the next release.", "3.0.0-RC7") def install[R](httpApp: HttpApp[R])(implicit trace: Trace, tag: EnvironmentTag[R]): URIO[R with Server, Int] = { - ZIO.serviceWithZIO[Server](_.install[R](httpApp)) *> ZIO.service[Server].map(_.port) + ZIO.serviceWithZIO[Server](_.install[R](httpApp)) *> ZIO.serviceWith[Server](_.port) } def serve[R]( diff --git a/zio-http/shared/src/main/scala/zio/http/WebSocketApp.scala b/zio-http/shared/src/main/scala/zio/http/WebSocketApp.scala index 199cd592ee..ec4176b83c 100644 --- a/zio-http/shared/src/main/scala/zio/http/WebSocketApp.scala +++ b/zio-http/shared/src/main/scala/zio/http/WebSocketApp.scala @@ -72,7 +72,7 @@ final case class WebSocketApp[-R]( Response.fromSocketApp(self.provideEnvironment(env)) } - @deprecated("Use toRoutes. Will be removed in the next release.") + @deprecated("Use toRoutes. Will be removed in the next release.", "3.0.0-RC7") def toHttpAppWS(implicit trace: Trace): HttpApp[R] = Handler.fromZIO(self.toResponse).toHttpApp diff --git a/zio-http/shared/src/main/scala/zio/http/WithContext.scala b/zio-http/shared/src/main/scala/zio/http/WithContext.scala index 01a521d44d..f7aa2aa107 100644 --- a/zio-http/shared/src/main/scala/zio/http/WithContext.scala +++ b/zio-http/shared/src/main/scala/zio/http/WithContext.scala @@ -57,7 +57,7 @@ private[http] trait WithContextConstructorLowPriorityImplicits1 extends WithCont ZIO.suspendSucceed { FiberRef.currentEnvironment.get.flatMap(environment => - z(environment.unsafe.get(tag1_), environment.unsafe.get(tag2_)), + z(environment.unsafe.get[Ctx1](tag1_), environment.unsafe.get[Ctx2](tag2_)), ) } } @@ -82,7 +82,11 @@ private[http] trait WithContextConstructorLowPriorityImplicits1 extends WithCont implicit val tag3_ = tag3.tag implicit val usf = Unsafe.unsafe FiberRef.currentEnvironment.get.flatMap(environment => - z(environment.unsafe.get(tag1_), environment.unsafe.get(tag2_), environment.unsafe.get(tag3_)), + z( + environment.unsafe.get[Ctx1](tag1_), + environment.unsafe.get[Ctx2](tag2_), + environment.unsafe.get[Ctx3](tag3_), + ), ) } @@ -113,10 +117,10 @@ private[http] trait WithContextConstructorLowPriorityImplicits1 extends WithCont implicit val usf = Unsafe.unsafe FiberRef.currentEnvironment.get.flatMap(environment => z( - environment.unsafe.get(tag1_), - environment.unsafe.get(tag2_), - environment.unsafe.get(tag3_), - environment.unsafe.get(tag4_), + environment.unsafe.get[Ctx1](tag1_), + environment.unsafe.get[Ctx2](tag2_), + environment.unsafe.get[Ctx3](tag3_), + environment.unsafe.get[Ctx4](tag4_), ), ) } @@ -150,11 +154,11 @@ private[http] trait WithContextConstructorLowPriorityImplicits1 extends WithCont implicit val usf = Unsafe.unsafe FiberRef.currentEnvironment.get.flatMap(environment => z( - environment.unsafe.get(tag1_), - environment.unsafe.get(tag2_), - environment.unsafe.get(tag3_), - environment.unsafe.get(tag4_), - environment.unsafe.get(tag5_), + environment.unsafe.get[Ctx1](tag1_), + environment.unsafe.get[Ctx2](tag2_), + environment.unsafe.get[Ctx3](tag3_), + environment.unsafe.get[Ctx4](tag4_), + environment.unsafe.get[Ctx5](tag5_), ), ) } @@ -177,7 +181,7 @@ private[http] trait WithContextConstructorLowPriorityImplicits2 extends WithCont implicit val usf = Unsafe.unsafe ZIO.suspendSucceed { - FiberRef.currentEnvironment.get.flatMap(environment => z(environment.unsafe.get(tag_))) + FiberRef.currentEnvironment.get.flatMap(environment => z(environment.unsafe.get[Ctx0](tag_))) } } } @@ -200,7 +204,7 @@ private[http] trait WithContextConstructorLowPriorityImplicits3 extends WithCont implicit val tag2_ = tag2.tag implicit val usf = Unsafe.unsafe FiberRef.currentEnvironment.get.map(environment => - z(environment.unsafe.get(tag1_), environment.unsafe.get(tag2_)), + z(environment.unsafe.get[Ctx1](tag1_), environment.unsafe.get[Ctx2](tag2_)), ) } @@ -224,7 +228,11 @@ private[http] trait WithContextConstructorLowPriorityImplicits3 extends WithCont implicit val tag3_ = tag3.tag implicit val usf = Unsafe.unsafe FiberRef.currentEnvironment.get.map(environment => - z(environment.unsafe.get(tag1_), environment.unsafe.get(tag2_), environment.unsafe.get(tag3_)), + z( + environment.unsafe.get[Ctx1](tag1_), + environment.unsafe.get[Ctx2](tag2_), + environment.unsafe.get[Ctx3](tag3_), + ), ) } } @@ -250,10 +258,10 @@ private[http] trait WithContextConstructorLowPriorityImplicits3 extends WithCont implicit val usf = Unsafe.unsafe FiberRef.currentEnvironment.get.map(environment => z( - environment.unsafe.get(tag1_), - environment.unsafe.get(tag2_), - environment.unsafe.get(tag3_), - environment.unsafe.get(tag4_), + environment.unsafe.get[Ctx1](tag1_), + environment.unsafe.get[Ctx2](tag2_), + environment.unsafe.get[Ctx3](tag3_), + environment.unsafe.get[Ctx4](tag4_), ), ) } @@ -287,11 +295,11 @@ private[http] trait WithContextConstructorLowPriorityImplicits3 extends WithCont implicit val usf = Unsafe.unsafe FiberRef.currentEnvironment.get.map(environment => z( - environment.unsafe.get(tag1_), - environment.unsafe.get(tag2_), - environment.unsafe.get(tag3_), - environment.unsafe.get(tag4_), - environment.unsafe.get(tag5_), + environment.unsafe.get[Ctx1](tag1_), + environment.unsafe.get[Ctx2](tag2_), + environment.unsafe.get[Ctx3](tag3_), + environment.unsafe.get[Ctx4](tag4_), + environment.unsafe.get[Ctx5](tag5_), ), ) } diff --git a/zio-http/shared/src/main/scala/zio/http/codec/Doc.scala b/zio-http/shared/src/main/scala/zio/http/codec/Doc.scala index e55c6524c6..628cc59856 100644 --- a/zio-http/shared/src/main/scala/zio/http/codec/Doc.scala +++ b/zio-http/shared/src/main/scala/zio/http/codec/Doc.scala @@ -271,7 +271,7 @@ sealed trait Doc { self => renderHelpDoc(right) case Doc.Raw(value, RawDocType.Plain) => - writer.append(value) + writer.append(value): Unit case Doc.Raw(_, docType) => throw new IllegalArgumentException(s"Unsupported raw doc type: $docType") diff --git a/zio-http/shared/src/main/scala/zio/http/codec/HttpCodec.scala b/zio-http/shared/src/main/scala/zio/http/codec/HttpCodec.scala index b68798e59f..7669c069dd 100644 --- a/zio-http/shared/src/main/scala/zio/http/codec/HttpCodec.scala +++ b/zio-http/shared/src/main/scala/zio/http/codec/HttpCodec.scala @@ -16,8 +16,6 @@ package zio.http.codec -import java.util.concurrent.ConcurrentHashMap - import scala.annotation.tailrec import scala.language.implicitConversions import scala.reflect.ClassTag @@ -313,10 +311,10 @@ object HttpCodec extends ContentCodecs with HeaderCodecs with MethodCodecs with def enumeration[Value]: Enumeration[Value] = new Enumeration[Value](()) - def error[Body](status: zio.http.Status)(implicit - schema: Schema[Body], - ): HttpCodec[HttpCodecType.Status with HttpCodecType.Content, Body] = - content[Body]("error-response") ++ this.status(status) + def error[Body0](status: zio.http.Status)(implicit + schema: Schema[Body0], + ): HttpCodec[HttpCodecType.Status with HttpCodecType.Content, Body0] = + content[Body0]("error-response") ++ this.status(status) private[http] sealed trait AtomTag private[http] object AtomTag { diff --git a/zio-http/shared/src/main/scala/zio/http/codec/PathCodec.scala b/zio-http/shared/src/main/scala/zio/http/codec/PathCodec.scala index a268b3eb2d..765ddb371b 100644 --- a/zio-http/shared/src/main/scala/zio/http/codec/PathCodec.scala +++ b/zio-http/shared/src/main/scala/zio/http/codec/PathCodec.scala @@ -387,7 +387,7 @@ object PathCodec { def apply(value: String): PathCodec[Unit] = { val path = Path(value) - path.segments match { + (path.segments: @unchecked) match { case Chunk() => PathCodec.empty case Chunk(first, rest @ _*) => rest.foldLeft[PathCodec[Unit]](Segment(SegmentCodec.literal(first))) { (pathSpec, segment) => diff --git a/zio-http/shared/src/main/scala/zio/http/endpoint/Endpoint.scala b/zio-http/shared/src/main/scala/zio/http/endpoint/Endpoint.scala index 29792d7835..475d7e2840 100644 --- a/zio-http/shared/src/main/scala/zio/http/endpoint/Endpoint.scala +++ b/zio-http/shared/src/main/scala/zio/http/endpoint/Endpoint.scala @@ -16,6 +16,7 @@ package zio.http.endpoint +import scala.annotation.nowarn import scala.reflect.ClassTag import zio._ @@ -45,6 +46,7 @@ import zio.http.endpoint.Endpoint.{OutErrors, defaultMediaTypes} * to generate a type-safe Scala client for the endpoint, and possibly, to * generate client libraries in other programming languages. */ +@nowarn("msg=type parameter .* defined") final case class Endpoint[PathInput, Input, Err, Output, Middleware <: EndpointMiddleware]( route: RoutePattern[PathInput], input: HttpCodec[HttpCodecType.RequestType, Input], @@ -727,6 +729,7 @@ object Endpoint { EndpointMiddleware.None, ) + @nowarn("msg=type parameter .* defined") final case class OutErrors[PathInput, Input, Err, Output, Middleware <: EndpointMiddleware, Err2]( self: Endpoint[PathInput, Input, Err, Output, Middleware], ) extends AnyVal { diff --git a/zio-http/shared/src/main/scala/zio/http/endpoint/openapi/JsonSchema.scala b/zio-http/shared/src/main/scala/zio/http/endpoint/openapi/JsonSchema.scala index 45197dc47b..e25d8b85a0 100644 --- a/zio-http/shared/src/main/scala/zio/http/endpoint/openapi/JsonSchema.scala +++ b/zio-http/shared/src/main/scala/zio/http/endpoint/openapi/JsonSchema.scala @@ -1,5 +1,7 @@ package zio.http.endpoint.openapi +import scala.annotation.nowarn + import zio._ import zio.json.ast.Json @@ -11,6 +13,7 @@ import zio.schema.codec.json._ import zio.http.codec.{SegmentCodec, TextCodec} +@nowarn("msg=possible missing interpolator") private[openapi] case class SerializableJsonSchema( @fieldName("$ref") ref: Option[String] = None, @fieldName("type") schemaType: Option[TypeOrTypes] = None, diff --git a/zio-http/shared/src/main/scala/zio/http/endpoint/openapi/OpenAPI.scala b/zio-http/shared/src/main/scala/zio/http/endpoint/openapi/OpenAPI.scala index 9cd11a5496..76dd5a8105 100644 --- a/zio-http/shared/src/main/scala/zio/http/endpoint/openapi/OpenAPI.scala +++ b/zio-http/shared/src/main/scala/zio/http/endpoint/openapi/OpenAPI.scala @@ -18,6 +18,7 @@ package zio.http.endpoint.openapi import java.net.URI +import scala.annotation.nowarn import scala.collection.immutable.ListMap import scala.util.matching.Regex @@ -499,6 +500,7 @@ object OpenAPI { * to link to parameters that are defined at the OpenAPI Object’s * components/parameters. */ + @nowarn("msg=possible missing interpolator") final case class PathItem( @fieldName("$ref") ref: Option[String], summary: Option[String], @@ -1194,6 +1196,7 @@ object OpenAPI { implicit def schema[T: Schema]: Schema[ReferenceOr[T]] = DeriveSchema.gen[ReferenceOr[T]] + @nowarn("msg=possible missing interpolator") final case class Reference( @fieldName("$ref") ref: String, summary: Option[Doc] = None, diff --git a/zio-http/shared/src/main/scala/zio/http/endpoint/openapi/OpenAPIGen.scala b/zio-http/shared/src/main/scala/zio/http/endpoint/openapi/OpenAPIGen.scala index fff71ea697..e8595f0656 100644 --- a/zio-http/shared/src/main/scala/zio/http/endpoint/openapi/OpenAPIGen.scala +++ b/zio-http/shared/src/main/scala/zio/http/endpoint/openapi/OpenAPIGen.scala @@ -795,8 +795,14 @@ object OpenAPIGen { alternatives.map { codec => val statusOrDefault = status(codec).map(OpenAPI.StatusOrDefault.StatusValue(_)).getOrElse(OpenAPI.StatusOrDefault.Default) - statusOrDefault -> (AtomizedMetaCodecs - .flatten(codec), contentAsJsonSchema(codec, referenceType = referenceType) _) + ( + statusOrDefault, + ( + AtomizedMetaCodecs + .flatten(codec), + contentAsJsonSchema(codec, referenceType = referenceType) _, + ), + ) } groupMap(statusAndCodec) { case (status, _) => status } { case (_, atomizedAndSchema) => @@ -805,7 +811,7 @@ object OpenAPIGen { val mapped = values .foldLeft(Chunk.empty[(MediaType, (AtomizedMetaCodecs, JsonSchema))]) { case (acc, (atomized, schema)) => if (atomized.content.size > 1) { - acc :+ (MediaType.multipart.`form-data` -> (atomized, schema(MediaType.multipart.`form-data`))) + acc :+ ((MediaType.multipart.`form-data`, (atomized, schema(MediaType.multipart.`form-data`)))) } else { val mediaType = atomized.content.headOption match { case Some(MetaCodec(HttpCodec.Content(codec, _, _), _)) => @@ -816,14 +822,14 @@ object OpenAPIGen { case _ => MediaType.application.`json` } - acc :+ (mediaType -> (atomized, schema(mediaType))) + acc :+ ((mediaType, (atomized, schema(mediaType)))) } } status -> groupMap(mapped) { case (mediaType, _) => mediaType } { case (_, atomizedAndSchema) => atomizedAndSchema }.map { case (mediaType, Chunk((atomized, schema))) if values.size == 1 => - mediaType -> (schema, atomized) + (mediaType, (schema, atomized)) case (mediaType, values) => val combinedAtomized: AtomizedMetaCodecs = values.map(_._1).reduce(_ ++ _) val combinedContentDoc = combinedAtomized.contentDocs.toCommonMark @@ -838,7 +844,7 @@ object OpenAPIGen { .minify .description(combinedContentDoc) } - mediaType -> (alternativesSchema, combinedAtomized) + (mediaType, (alternativesSchema, combinedAtomized)) } } } diff --git a/zio-http/shared/src/main/scala/zio/http/multipart/mixed/MultipartMixed.scala b/zio-http/shared/src/main/scala/zio/http/multipart/mixed/MultipartMixed.scala index 6c2ac2f465..bb0033365d 100644 --- a/zio-http/shared/src/main/scala/zio/http/multipart/mixed/MultipartMixed.scala +++ b/zio-http/shared/src/main/scala/zio/http/multipart/mixed/MultipartMixed.scala @@ -123,7 +123,7 @@ object MultipartMixed { if (boundary.isClosing(h)) ZChannel.succeed((res, rest, true)) else if (boundary.isEncapsulating(h)) // ditto - ZChannel.succeed(res, rest, false) + ZChannel.succeed((res, rest, false)) else { // todo: this is a private class, either avoid using it or refactor FormAST.Header diff --git a/zio-http/shared/src/main/scala/zio/http/package.scala b/zio-http/shared/src/main/scala/zio/http/package.scala index 977df0eb85..b35a9971fe 100644 --- a/zio-http/shared/src/main/scala/zio/http/package.scala +++ b/zio-http/shared/src/main/scala/zio/http/package.scala @@ -36,15 +36,6 @@ package object http extends UrlInterpolator with MdInterpolator { def withContext[C](fn: => C)(implicit c: WithContext[C]): ZIO[c.Env, c.Err, c.Out] = c.toZIO(fn) - abstract class RouteDecode[A](f: String => A) { - def unapply(a: String): Option[A] = - try { - Option(f(a)) - } catch { - case _: Throwable => None - } - } - def boolean(name: String): PathCodec[Boolean] = PathCodec.bool(name) def int(name: String): PathCodec[Int] = PathCodec.int(name) def long(name: String): PathCodec[Long] = PathCodec.long(name)