This release is a result of fixing an old known issue when an encoder, resolved for a given type A
doesn't take into an account a Content-Type of A
. This is why, for example, an import io.finch.circe._
makes everything JSON.
This release also made it a new record: 24 contributors! Thank you!
Before looking closely into the changes were made, it's worth mentioning that there is now a Roadmap 1.0 available as a wiki page. It's not super clear yet how long it will take, but at least, we now have a finite list of things to-do.
Why M1?
This is just a first step (marked as M1) towards more type safety in Finch. While the solution released here is not complete, I decided to wrap up a release and let people play with initial bits, while postponing the rest of the things to M2. It's been almost 6 months since the previous release and I feel it's important to do a release (even the M-prefixed one) now, given that besides type-level content type, it also contains a number of improvements for memory and performance.
Please, note that the solution is presented here doesn't allow (doesn't compile) mixing endpoints of different content types in a single call .toService
. While this sounds like a dramatic restriction, this should be viewed as a temporary step towards fully working solution that should a part of 0.11.
That said, please, consider upgrade if you only serve JSON (or anything) within your Finch server. Otherwise, would be reasonable to wait for 0.11.
Content-Type as a Type
There is now a much better way to handle content-types in Finch. A content-type is now a type-level string (see #541) and it does affect an implicit resolution of encoders, so, for example, if you ask for Encode.Text[A]
, and you only have Circe's encoders (JSON encoders) in the scope, your program won't compile. This a huge step towards a better utilization of Scala's type-system and capturing just a little more information in types.
Given that content-type is now a separate concept, which is neither attached to Endpoint
nor Output
, a way to specify it is to explicitly pass a requested content-type to a toService
method call (using toServiceAs
variant).
Please, note that Output.withContentType
is gone since it was just a lie.
Before (broken at runtime):
// helloWorld is a text/plain endpoint that will be encoded by whatever encoder is in the scope
// (eg: if Circe is imported it will be a JSON string)
val api: Service[Request, Response] = (
getUsers :+: postUsers :+: helloWorld
).toService
After (broken at compile time):
val api: Service[Request, Response] = (
getUsers :+: postUsers :+: helloWorld
).toServiceAs[Application.Json]
JSON (i.e., Application.Json
) is a default content-type for the to.Service
call.
Charsets Make Difference
Previously, charsets set on Output
don't make much of difference to the HTTP response service with Finch, rather than changing the Content-Type
header. Now they are propagated to the encoder (see #610). For the sake of type-safety, a charset is now java.nio.charset.Charset
, not String
.
This change implies some default behaviour that should be explained. By default, a charset on Output
is None
so it's not copied over to the HTTP response. Although, an encoder will be using UTF-8 as a default. That said, everything will be encoded as UTF-8, but the Content-Type
header won't be caring information about the charset.
Set charset either on Endpoint
or Output
to make it explicit (and propogated to the HTTP response).
New Endpoints
There are two new endpoints (see #606):
Endpoint.empty[A]
that never matchesroot: Endpoint[Request]
that extracts an entire HTTP requests
Better Performance
Finch now uses Catbird's Rerunnable[A]
instead of Eval[Future[A]]
(see #578) and performs 20-30% better due to a reduced number of allocations.
Better Cats Integration
- There is now an
Alternative
instance forEndpoint
provided out of the box (see #551). - New endpoint
paramsNel
returns Cat'sNonEmptyList
(see #582)
Better Encoding
- It's now possible to JSON stream anything that has a JSON encoder (see #566)
- Anything that has a
cats.Show
instance now derivesEncode.PlainText
and so might be served astext/plain
(see #561)
New Packages
Better Generic Derivation
Endpoint.derive[Foo].fromParams
now takes into an account optional params deriving paramOption
and multi-value params deriving either params
or paramsNel
(see #577).
Updated Dependencies
- Finagle 6.35
- Circe 0.5.0-M2
- Cats 0.6
- Shapeless 2.3