Skip to content

Commit

Permalink
Merge pull request http4s#7296 from http4s/pr/merge-0.23-main-20231004
Browse files Browse the repository at this point in the history
0.23 -> main
  • Loading branch information
armanbilge authored Oct 19, 2023
2 parents 3e90c7a + d0edad4 commit 68df084
Show file tree
Hide file tree
Showing 96 changed files with 888 additions and 629 deletions.
3 changes: 3 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,6 @@ a650b1cc735db81a0d4743590001e89118a8536e

# Scala Steward: Reformat with scalafmt 3.7.0
8cac378a431a8a786b26469c7c675d4f90e29dc6

# Scala Steward: Reformat with scalafmt 3.7.5
ab3b86443600f9038700cc11419934db1770fa08
402 changes: 299 additions & 103 deletions .github/workflows/ci.yml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .scalafmt.conf
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version = 3.7.4
version = 3.7.14

style = default

Expand Down
72 changes: 34 additions & 38 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,30 @@ import org.http4s.sbt.Http4sPlugin._

// Global settings
ThisBuild / crossScalaVersions := Seq(scala_3, scala_213)
ThisBuild / tlBspCrossProjectPlatforms := Set(JVMPlatform)
ThisBuild / tlBaseVersion := "1.0"
ThisBuild / developers += tlGitHubDev("rossabaker", "Ross A. Baker")

ThisBuild / tlCiReleaseBranches := Seq("main")
ThisBuild / tlSitePublishBranch := Some("main")

ThisBuild / semanticdbOptions ++= Seq("-P:semanticdb:synthetics:on").filter(_ => !tlIsScala3.value)

ThisBuild / scalafixAll / skip := tlIsScala3.value
ThisBuild / ScalafixConfig / skip := tlIsScala3.value
ThisBuild / Test / scalafixConfig := Some(file(".scalafix.test.conf"))

ThisBuild / githubWorkflowJobSetup ~= {
_.filterNot(_.name.exists(_.matches("(Download|Setup) Java .+")))
ThisBuild / githubWorkflowJobSetup ~= { steps =>
Seq(
WorkflowStep.Use(
UseRef.Public("cachix", "install-nix-action", "v20"),
name = Some("Install Nix"),
),
WorkflowStep.Use(
UseRef.Public("cachix", "cachix-action", "v12"),
name = Some("Install Cachix"),
params = Map("name" -> "http4s", "authToken" -> "${{ secrets.CACHIX_AUTH_TOKEN }}"),
),
) ++ steps
}
ThisBuild / githubWorkflowJobSetup ++= Seq(
WorkflowStep.Use(
UseRef.Public("cachix", "install-nix-action", "v20"),
name = Some("Install Nix"),
),
WorkflowStep.Use(
UseRef.Public("cachix", "cachix-action", "v12"),
name = Some("Install Cachix"),
params = Map("name" -> "http4s", "authToken" -> "${{ secrets.CACHIX_AUTH_TOKEN }}"),
),
)

ThisBuild / githubWorkflowSbtCommand := "nix develop .#${{ matrix.java }} -c sbt"

Expand All @@ -46,7 +44,7 @@ ThisBuild / githubWorkflowAddedJobs ++= Seq(
UseRef.Public(
"codecov",
"codecov-action",
"v2",
"v3",
),
cond = Some("github.event_name != 'pull_request'"),
),
Expand Down Expand Up @@ -87,7 +85,6 @@ lazy val modules: List[CompositeProject] = List(
)

lazy val root = tlCrossRootProject
.disablePlugins(ScalafixPlugin)
.settings(
// Root project
name := "http4s",
Expand Down Expand Up @@ -133,26 +130,10 @@ lazy val core = libraryCrossProject("core")
)
.platformsSettings(JSPlatform, NativePlatform)(
libraryDependencies ++= Seq(
log4catsNoop.value,
scalaJavaLocalesEnUS.value,
scalaJavaTime.value,
)
)
.jvmSettings(
libraryDependencies ++= {
Seq(log4catsSlf4j)
},
libraryDependencies ++= {
if (tlIsScala3.value) Seq.empty
else
Seq(
slf4jApi // residual dependency from macros
)
},
)
.jsSettings(
libraryDependencies ++= Seq(log4catsJSConsole.value)
)

lazy val laws = libraryCrossProject("laws", CrossType.Pure)
.settings(
Expand Down Expand Up @@ -403,7 +384,7 @@ lazy val docs = http4sProject("site")
log4catsSlf4j,
),
description := "Documentation for http4s",
tlFatalWarningsInCi := false,
tlFatalWarnings := false,
fork := false,
)
.dependsOn(
Expand Down Expand Up @@ -434,7 +415,7 @@ lazy val examplesEmber = exampleProject("examples-ember")
description := "Examples of http4s server and clients on ember",
startYear := Some(2020),
fork := true,
scalacOptions -= "-Xfatal-warnings",
tlFatalWarnings := false,
coverageEnabled := false,
)
.dependsOn(emberServer.jvm, emberClient.jvm)
Expand All @@ -454,9 +435,14 @@ lazy val examplesDocker = http4sProject("examples-docker")
)
.dependsOn(emberServer.jvm, theDsl.jvm)

lazy val scalafixInternalSettings = Seq(
unusedCompileDependenciesFilter -= moduleFilter("org.typelevel", "scalac-compat-annotation")
)

lazy val scalafixInternalRules = project
.in(file("scalafix-internal/rules"))
.disablePlugins(ScalafixPlugin)
.settings(scalafixInternalSettings)
.settings(
name := "http4s-scalafix-internal",
mimaPreviousArtifacts := Set.empty,
Expand All @@ -470,21 +456,31 @@ lazy val scalafixInternalInput = project
.in(file("scalafix-internal/input"))
.enablePlugins(NoPublishPlugin)
.disablePlugins(ScalafixPlugin)
.settings(headerSources / excludeFilter := AllPassFilter, scalacOptions -= "-Xfatal-warnings")
.settings(scalafixInternalSettings)
.settings(
headerSources / excludeFilter := AllPassFilter,
tlFatalWarnings := false,
semanticdbOptions ++= Seq("-P:semanticdb:synthetics:on").filter(_ => !tlIsScala3.value),
)
.dependsOn(core.jvm)

lazy val scalafixInternalOutput = project
.in(file("scalafix-internal/output"))
.enablePlugins(NoPublishPlugin)
.disablePlugins(ScalafixPlugin)
.settings(headerSources / excludeFilter := AllPassFilter, scalacOptions -= "-Xfatal-warnings")
.settings(scalafixInternalSettings)
.settings(
headerSources / excludeFilter := AllPassFilter,
tlFatalWarnings := false,
)
.dependsOn(core.jvm)

lazy val scalafixInternalTests = project
.in(file("scalafix-internal/tests"))
.enablePlugins(NoPublishPlugin)
.enablePlugins(ScalafixTestkitPlugin)
.settings(
startYear := Some(2021),
libraryDependencies := {
if (tlIsScala3.value)
libraryDependencies.value.filterNot(_.name == "scalafix-testkit")
Expand All @@ -502,7 +498,7 @@ lazy val scalafixInternalTests = project
scalafixTestkitInputScalacOptions := (scalafixInternalInput / Compile / scalacOptions).value,
scalacOptions += "-Yrangepos",
)
.settings(headerSources / excludeFilter := AllPassFilter)
.settings(scalafixInternalSettings)
.disablePlugins(ScalafixPlugin)
.dependsOn(scalafixInternalRules)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ object WSTestClient {

implicit private[http4s] class WebSocketFrameOps(val wsf: WebSocketFrame) {
def toWSFrame: WSFrame =
wsf match {
(wsf: @unchecked) match {
case c: WebSocketFrame.Close => WSFrame.Close(c.closeCode, c.reason)
case WebSocketFrame.Ping(data) => WSFrame.Ping(data)
case WebSocketFrame.Pong(data) => WSFrame.Pong(data)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,6 @@ class FollowRedirectSuite extends Http4sSuite with Http4sClientDsl[IO] {
private val defaultClient = Client.fromHttpApp(app)
private val client = FollowRedirect(3)(defaultClient)

private case class RedirectResponse(
method: String,
body: String,
)

test("FollowRedirect should strip payload headers when switching to GET") {
// We could test others, and other scenarios, but this was a pain.
val req = Request[IO](PUT, uri"http://localhost/303").withEntity("foo")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class GZipSuite extends Http4sSuite {
Ok("Dummy response")
case HEAD -> Root / "gziptest" =>
Ok()
case _ => NotFound()
})
private val gzipClient = GZip()(Client.fromHttpApp(service))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class OAuthSuite extends Http4sSuite {
// some params taken from http://oauth.net/core/1.0/#anchor30, others from
// https://datatracker.ietf.org/doc/html/rfc5849

private val Right(uri) = Uri.fromString("http://photos.example.net/photos")
private val Right(uri) = Uri.fromString("http://photos.example.net/photos"): @unchecked
private val consumer = oauth1.Consumer("dpf43f3p2l4k3l03", "kd94hf93k423kf44")
private val token = oauth1.Token("nnch734d00sl2jdk", "pfkkdhi9sl3r4s00")

Expand Down Expand Up @@ -89,8 +89,9 @@ class OAuthSuite extends Http4sSuite {
implicit def urlFormEncoder: EntityEncoder[IO, UrlForm] =
UrlForm.entityEncoder(Charset.`US-ASCII`)

val Right(uri) = Uri.fromString("http://example.com/request?b5=%3D%253D&a3=a&c%40=&a2=r%20b")
val Right(body) = UrlForm.decodeString(Charset.`US-ASCII`)("c2&a3=2+q")
val Right(uri) =
Uri.fromString("http://example.com/request?b5=%3D%253D&a3=a&c%40=&a2=r%20b"): @unchecked
val Right(body) = UrlForm.decodeString(Charset.`US-ASCII`)("c2&a3=2+q"): @unchecked

val req = Request[IO](method = Method.POST, uri = uri).withEntity(body)

Expand Down Expand Up @@ -151,7 +152,7 @@ class OAuthSuite extends Http4sSuite {

def fixedTS: IO[Timestamp] = IO(Timestamp("1628332200"))
def fixedNonce: IO[Nonce] = IO(Nonce("123456789"))
val Right(uri) = Uri.fromString("http://www.peepandthebigwideworld.com/")
val Right(uri) = Uri.fromString("http://www.peepandthebigwideworld.com/"): @unchecked

oauth1
.signRequest(
Expand Down
5 changes: 0 additions & 5 deletions core/native/src/main/scala/org/http4s/Platform.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,8 @@

package org.http4s

import cats.effect.SyncIO
import org.typelevel.log4cats

private[http4s] object Platform {
final val isJvm = false
final val isJs = false
final val isNative = true

lazy val loggerFactory: log4cats.LoggerFactory[SyncIO] = log4cats.noop.NoOpFactory[SyncIO]
}
4 changes: 3 additions & 1 deletion core/shared/src/main/scala/org/http4s/Charset.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import java.util.HashMap
import java.util.Locale
import scala.jdk.CollectionConverters._

final case class Charset private[http4s] (nioCharset: NioCharset) extends Renderable {
final case class Charset private (nioCharset: NioCharset) extends Renderable {
def withQuality(q: QValue): CharsetRange.Atom = CharsetRange.Atom(this, q)
def toRange: CharsetRange.Atom = withQuality(QValue.One)

Expand All @@ -44,6 +44,8 @@ final case class Charset private[http4s] (nioCharset: NioCharset) extends Render

object Charset {

def apply(nioCharset: NioCharset): Charset = new Charset(nioCharset)

implicit val catsInstancesForHttp4sCharset: Hash[Charset] with Order[Charset] =
new Hash[Charset] with Order[Charset] {
override def hash(x: Charset): Int =
Expand Down
10 changes: 8 additions & 2 deletions core/shared/src/main/scala/org/http4s/CharsetRange.scala
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,19 @@ object CharsetRange {

object `*` extends `*`(QValue.One)

final case class Atom protected[http4s] (charset: Charset, qValue: QValue = QValue.One)
extends CharsetRange {
final case class Atom private (
charset: Charset,
qValue: QValue = QValue.One,
) extends CharsetRange {
override def withQValue(q: QValue): CharsetRange.Atom = copy(qValue = q)

def render(writer: Writer): writer.type = writer << charset << qValue
}

object Atom {
def apply(charset: Charset, qValue: QValue = QValue.One): Atom = new Atom(charset, qValue)
}

implicit def fromCharset(cs: Charset): CharsetRange.Atom = cs.toRange

implicit val http4sEqForCharsetRange: Eq[CharsetRange] = Eq.fromUniversalEquals
Expand Down
28 changes: 18 additions & 10 deletions core/shared/src/main/scala/org/http4s/Credentials.scala
Original file line number Diff line number Diff line change
Expand Up @@ -102,21 +102,29 @@ object BasicCredentials {
private def decode(bytes: Array[Byte], charset: JavaCharset): String =
new String(bytes, charset)

def apply(token: String): BasicCredentials = {
val bytes = Base64.getDecoder.decode(token)
val (userPass, charset) = decode(bytes, utf8CharsetDecoder)
.fold(_ => (decode(bytes, fallbackCharset), fallbackCharset), up => (up, utf8Charset))
userPass.indexOf(':') match {
case -1 => apply(userPass, "", charset)
case ix => apply(userPass.substring(0, ix), userPass.substring(ix + 1), charset)
private def fromString0(token: String): Try[BasicCredentials] =
Try(Base64.getDecoder.decode(token)).map { bytes =>
val (userPass, charset) = decode(bytes, utf8CharsetDecoder)
.fold(_ => (decode(bytes, fallbackCharset), fallbackCharset), up => (up, utf8Charset))
userPass.indexOf(':') match {
case -1 => apply(userPass, "", charset)
case ix => apply(userPass.substring(0, ix), userPass.substring(ix + 1), charset)
}
}
}

@deprecated("Use fromString instead", "0.23.24")
def apply(token: String): BasicCredentials =
fromString0(token).get

def fromString(token: String): Option[BasicCredentials] =
fromString0(token).toOption

def unapply(creds: Credentials): Option[(String, String)] =
creds match {
case Credentials.Token(AuthScheme.Basic, token) =>
val basicCredentials = BasicCredentials(token)
Some((basicCredentials.username, basicCredentials.password))
fromString(token).map { basicCredentials =>
(basicCredentials.username, basicCredentials.password)
}
case _ =>
None
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import cats.syntax.all._
* scala> import cats.syntax.all._
* scala> import cats.data._
* scala> import org.http4s.FormDataDecoder._
* scala> import org.http4s.ParseFailure
* scala> case class Foo(a: String, b: Boolean)
* scala> case class Bar(fs: List[Foo], f: Foo, d: Boolean)
* scala>
Expand Down
2 changes: 1 addition & 1 deletion core/shared/src/main/scala/org/http4s/Headers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ final class Headers(val headers: List[Header.Raw]) extends AnyVal {
case `Transfer-Encoding`.name =>
`Transfer-Encoding`
.parse(h.value)
.redeem(
.redeem[Unit](
_ => b += h,
_.filter(_ != TransferCoding.chunked)
.foreach(b += _.toRaw1),
Expand Down
2 changes: 2 additions & 0 deletions core/shared/src/main/scala/org/http4s/HttpVersion.scala
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ final case class HttpVersion private (major: Int, minor: Int)

object HttpVersion {

def apply(major: Int, minor: Int): HttpVersion = new HttpVersion(major, minor)

/** HTTP/0.9 was first formalized in the HTTP/1.0 spec. `HTTP/0.9`
* does not literally appear in the HTTP/0.9 protocol.
*
Expand Down
2 changes: 1 addition & 1 deletion core/shared/src/main/scala/org/http4s/MediaType.scala
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ object MediaType extends MimeDB {
private[http4s] def getMediaType(_mainType: String, _subType: String): MediaType = {
val mainType = _mainType.toLowerCase
val subType = _subType.toLowerCase
if (Platform.isJvm || Platform.isNative)
if (Platform.isJvm)
MediaType.all.getOrElse(
(mainType, subType),
new MediaType(mainType, subType),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ object ServerSentEvent {
case Some(("", stream)) =>
dispatch(stream)
case Some((s, stream)) =>
FieldSeparator.split(s, 2) match {
(FieldSeparator.split(s, 2): @unchecked) match {
case Array(field, value) =>
handleLine(field, value, stream)
case Array(line) =>
Expand Down
Loading

0 comments on commit 68df084

Please sign in to comment.