Releases: finagle/finch
Finch 0.34.0
With this release the Cats Effect based version of Finch becomes the official one! 🥳
It means that finchx
becomes finch
again and you need to update your artifact names,
this change will not be picked up automatically by Scala Steward!
And thanks to @tpetillot's this release comes with much anticipated support for Cats Effect 3! ❤️
What's Changed
- Rename artifacts finchx to finch by @vkostyukov in #1470
- Remove dead references to AsyncStream by @benjumanji in #1274
- chore: format on compile by @tpetillot in #1466
- Migration to cats-effect 3 by @tpetillot in #1472
- Remove ToAsync by @vkostyukov in #1480
- kind-projector 0.13.2 (was 0.10.3) by @SethTisue in #1483
- Get rid of RequestItem; rework Errors; remove ValidationRules by @vkostyukov in #1471
- Clean up examples to not use toAsync by @vkostyukov in #1481
- Add support for 406 Not Acceptable response on content negotiation by @joroKr21 in #1513
- Cleanup build by @joroKr21 in #1512
- Migrate Errors to NonEmptyChain and add a Semigroup instance by @joroKr21 in #1515
- Use ApplicativeThrow and MonadThrow type aliases by @joroKr21 in #1516
Dependency updates
- Update sbt-wartremover, wartremover to 3.0.0 by @scala-steward in #1473
- Update sbt-wartremover, wartremover to 3.0.1 by @scala-steward in #1474
- Update sbt-wartremover, wartremover to 3.0.2 by @scala-steward in #1475
- Update scalafmt-core to 3.5.2 by @scala-steward in #1477
- Update finagle-http, finagle-stats, ... to 22.4.0 by @scala-steward in #1479
- Update scalatest to 3.2.12 by @scala-steward in #1482
- Update sbt-wartremover, wartremover to 3.0.3 by @scala-steward in #1484
- Update refined, refined-cats, ... to 0.9.29 by @scala-steward in #1485
- Update sbt-wartremover, wartremover to 3.0.4 by @scala-steward in #1487
- Update circe-core, circe-generic, ... to 0.14.2 by @scala-steward in #1488
- Update cats-effect to 3.3.12 by @scala-steward in #1489
- Update sbt-sonatype to 3.9.13 by @scala-steward in #1490
- Update refined, refined-cats, ... to 0.10.0 by @scala-steward in #1494
- Update fs2-core to 3.2.9 by @scala-steward in #1493
- Update sbt-scalafix to 0.10.1 by @scala-steward in #1492
- Update sbt-wartremover, wartremover to 3.0.5 by @scala-steward in #1502
- Update discipline-scalatest to 2.2.0 by @scala-steward in #1501
- Update cats-effect to 3.3.13 by @scala-steward in #1500
- Update cats-core, cats-laws to 2.8.0 by @scala-steward in #1499
- Update scalafmt-core to 3.5.8 by @scala-steward in #1497
- Update refined, refined-cats, ... to 0.10.1 by @scala-steward in #1495
- Update fs2-core to 3.2.10 by @scala-steward in #1503
- Update sbt to 1.7.1 by @scala-steward in #1504
- Update cats-effect to 3.3.14 by @scala-steward in #1505
- Update fs2-core to 3.2.11 by @scala-steward in #1506
- Update finagle-http, finagle-stats, ... to 22.7.0 by @scala-steward in #1508
- Update scalatest to 3.2.13 by @scala-steward in #1509
- Update fs2-core to 3.2.12 by @scala-steward in #1510
- Update scalafmt-core to 3.5.9 by @scala-steward in #1514
- Update sbt-wartremover, wartremover to 3.0.6 by @scala-steward in #1517
- Update fs2-core to 3.2.14 by @scala-steward in #1518
- Update shapeless to 2.3.10 by @scala-steward in #1519
- Update fs2-core to 3.3.0 by @scala-steward in #1520
New Contributors
- @SethTisue made their first contribution in #1483
Full Changelog: v0.33.0...v0.34.0
Finch 0.33
v0.33.0 Releasing 0.33.0
Finch 0.32.1
Hello Scala 2.13, bye 2.11
Long-awaited release for Scala 2.13 has finally arrived. Thanks for your patience as well as for all the efforts the community has made to update Finagle to 2.13.
We also drop the support for Scala 2.11, as some of the dependencies aren't available for that version.
Last release of finchx
artifacts. Long live the finch
This release is expected to be the last one for finchx
prefixed artifacts. Starting from the next update we're going to decommission the Future
-based finch
artifacts and replace it with polymorphic one.
Effectively, it means that no finchx
artifacts will be updated and you would need to update the dependency by dropping the x
letter.
To ensure the best developer experience we're going to groom existing documentation to make it up to date with all the exciting changes and capabilities of Finch.
Release notes
Finch 0.32
See 0.32.1
Finch 0.31
Finch 0.30.0
This is a release of Finch with Finagle 19.6.0.
In addition to version bumps of many libraries, this release has the following:
- Removal of the deprecated
transformOutput
Finch 0.29
Finch 0.28
This release introduces new functionality to build a middleware of your HTTP service.
Kleisli composition
Instead of converting Endpoint
straight into Service[Request, Response]
, there is now an option to compile it first into Kleisli[F[_], Request, (Trace, Either[Throwable, Response])]
data type (or Endpoint.Compiled[F]
as a type alias). It allows to replace most of the Finagle filters with Kleisli composition that is also effect-aware:
finch@ import cats.effect.IO
import cats.effect.IO
finch@ import cats.data.Kleisli
import cats.data.Kleisli
finch@ import io.finch._
import io.finch._
finch@ import io.finch.catsEffect._
import io.finch.catsEffect._
finch@ val endpoint = get("hello") {
Ok("world")
}
endpoint: Endpoint[IO, String] = GET /hello
finch@ val compiled = Bootstrap.serve[Text.Plain](endpoint).compile
compiled: Endpoint.Compiled[IO] = Kleisli(io.finch.Compile$$anon$2$$Lambda$2951/1251806319@7dccca17)
finch@ val authFilter = Kleisli.ask[IO, Request].andThen { req =>
if(req.authorization.isEmpty) IO.raiseError(new IllegalStateException())
else IO.pure(req)
}
authFilter: Kleisli[IO, Request, Request] = Kleisli(cats.data.Kleisli$$$Lambda$2999/1785722147@b53898c)
finch@ val finale = authFilter.andThen(compiled)
finale: Kleisli[IO, Request, (Trace, Either[Throwable, com.twitter.finagle.http.Response])] = Kleisli(cats.data.Kleisli$$$Lambda$2999/1785722147@7c51944f)
finch@ val service = Endpoint.toService(finale)
service: com.twitter.finagle.Service[Request, com.twitter.finagle.http.Response] = ToService(Kleisli(cats.data.Kleisli$$$Lambda$2999/1785722147@7c51944f))
finch@ service(Request("/hello"))
res38: com.twitter.util.Future[com.twitter.finagle.http.Response] = Promise@471126862(state=Done(Throw(java.lang.IllegalStateException)))
finch@ val req = Request("/hello")
req: Request = Request("GET /hello", from 0.0.0.0/0.0.0.0:0)
finch@ req.authorization = "user:password"
finch@ service(req)
res41: com.twitter.util.Future[com.twitter.finagle.http.Response] = Promise@1914269162(state=Done(Return(Response("HTTP/1.1 Status(200)"))))
Finch will do its best to prevent F[_]
from having an exception inside of compiled Endpoint and have it inside of the Either. Check out proper example how to build and compose filters together.
Endpoint.transformF and type classes refactoring
We've made a small refactoring over the Finch codebase to use as least powerful abstractions for effect F[_]
as possible. Now, in most of the places it's enough to have Sync
or Async
type classes available to build endpoints. It enables the use of things like StateT
, Kleisli
, and WriterT
as your effect type, thus propagating the data down the line using the effect. More examples and documentation on this later.
AsyncStream deprecation
asyncBody
deprecation cycle is over, consider to use fs2 or iteratee as a replacement in case if you need a streaming. Both of them are supported by corresponding Finch modules. Here is the simple example of how to use one.
Also, finch-sse was removed as a separate module. Related code moved to the core and finch-fs2 & finch-iteratee modules.
Join our community
If you have any questions or ideas, feel free to address them in issues or join our gitter channel.
Finch 0.27
This new release is featuring fs2 integration as well fully reworked streaming support, allowing for easier testing of streaming endpoints.
FS2 Support
#1042 adds fs2 support in Finch (thanks @sergeykolbasov). As of 0.27, it's now possible to receive and send JSON (or pretty much any arbitrary) streams using fs2's Stream
type. The new API entry point, bodyStream
, allows to construct streaming endpoints with the requested stream type, Enumerator
(iteratee) or Stream
(fs2).
scala> import fs2.Stream, io.finch._, io.finch.catsEffect._, io.finch.fs2._
scala> val bin = binaryBodyStream[Stream] // raw byte-array stream
bin: Endpoint[IO, fs2.Stream[IO, Array[Byte]]] = binaryBodyStream
scala> val str = stringBodyStream[Stream] // stream of strings
str: Endpoint[IO, fs2.Stream[IO, String]] = stringBodyStream
Similarly, accepting a stream of JSON object is possible via bodyStream
or jsonBodyStream
endpoints.
scala> import fs2.Stream, io.finch._, io.finch.catsEffect._, io.finch.fs2._
scala> import io.finch.circe._, io.circe.generic.auto._
scala> case class Foo(s: String)
defined class Foo
scala> val foos = bodyStream[Stream, Foo, Application.Json]
foos: Endpoint[IO,f s2.Stream[IO, Foo]] = bodyStream
scala> val foos = jsonBodyStream[Stream, Foo]
foos: Endpoint[IO, fs2.Stream[IO, Foo]] = bodyStream
Serving streaming bodies is no different from serving fully-buffered payloads, just return Stream
(fs2) or Enumerator
from an endpoint.
scala> import fs2.Stream, cats.effect.IO, io.finch._, io.finch.catsEffect._, io.finch.fs2._
scala> import io.finch.circe._, io.circe.generic.auto._
scala> case class Foo(s: String)
defined class Foo
scala> val foos = Endpoint[IO].const(Stream[IO, Foo](Foo("bar")))
foos: Endpoint[IO, fs2.Stream[IO, Foo]] = io.finch.Endpoint$$anon$34@5428e82e
scala> foos.toServiceAs[Application.Json]
res1: Service[Request, Response] = io.finch.ToService$$anon$4$$anon$2
Testing Streaming Endpoints
#1056 enables users to construct Input
instances with streaming bodies (non fully buffered). At this point, both fs2 and iteratee streams are supported.
import io.finch._, io.finch.iteratee._, io.interatee.Enumerator, cats.effect.IO
val i = Input
.post("/")
.withBody[Text.Plain](Enumerator.enumerate[IO, String]("foo", "bar", "baz"))
Creating an Input
out of a JSON stream is also possible:
import io.finch._, io.finch.iteratee._, io.interatee.Enumerator, cats.effect.IO
import io.finch.circe._, io.circe.generic.auto._
case class Foo(s: String)
val i = Input
.post("/")
.withBody[Application.Json](Enumerator.enumerate[IO, Foo](Foo("foo"), Foo("bar")))
Switching between iteratee and fs2 is as easy as replacing io.finch.iteratee._
import with io.finch.fs2._
.
Dependency Updates
Finch 0.26.1
🐞Bugfix release:
Endpoint.rescue
was incorretly throwingMatchError
if the exception inside of an effect was not defined for the given partitial function. The correct behavior is to re-raise the exception. This bug affected onlyfinchx-
modules. #1048