github finagle/finch 0.6.0
Finch 0.6.0

latest releases: v0.34.1, v0.34.0, v0.33.0...
9 years ago

This release involves several improvements of the core package as well as a new "easter egg" mode of Finch with codename "Your REST API as a Monad". Although, this release is 100% source-compatible with a previous version.

Please, note that while the old-style io.finch.Endopint is not deprecated yet, it's highly recommended to consider migration to route combinators.

Deprecations

There is a new naming conversion for RequestReaders that is heavily inspired by Scala standard library:

  • Every RequiredX is now just x, eg. param("a")
  • Every OptionalX is now xOption, eg. headerOption("X-Secret")

There is just one exclusion from this scheme:

  • RequiredParams is now paramsNonEmpty
  • OptionalParams is now params

New Features

  • There is a secret Finch mode available: deal with types that matter (see details bellow)
  • The RequestReader is now polymorphic in terms of request type (see details bellow)
  • There are two new RequestReaders: fileUpload and fileUploadOption that can read an upload (a multipart/form) param from the request
  • Both paramand paramOption are also looking at multipart/form content for param values
  • Two new combinators ~> and ~~> are available on RequestReader (see details bellow)
  • The /> combinator on Router is now more useful (see details bellow)
  • There is router ** that always matches an entire route
Your REST API as a Monad

There is a secret (ninja) mode available in this release. It's fully described in docs/micro.md. The basic idea is to replace Service (a function) with RequestReader (a monad), which basically does the same job but implies insane composability. While it's still an experimental approach, we believe that it solves the "Finch Puzzle" and dramatically simplifies the whole picture. We personally believe that his way is "the way" to write idiomatic and robust Finch code.

Polymorphic RequestReader[A] a la PRequestReader[R, A]

While this tiny change doesn't affect API, this is a huge step towards flexibility. Code speaks for them self, here is the current picture:

trait PRequestReader[R, A] {
  def apply(req: R): Future[A]
}

type RequestReader[A] = PRequestReader[HttpRequest, A]

That said, all the monadic and applicative operations are defined over the output type A (right associative).

Magic behind ~>, ~~> and /> combinators

Both ~> and ~~> compositors allow to threat underlying type A ~ B .. ~ Z as (A, B, ..., Z). So, the following code compiles:

def sum(i: Int, j: Int) = i + j
val r: RequestReader[Int] = 
  param("i").as[Int] ~ param("j").as[Int] ~> sum

Using the ~~> we can make long calls to the underlying async API (considering that Micro is RequestReader):

def fetchUserFromDb(id: Int): Future[User] = ???
def getUser: Micro[User] = RequiredParam("id").as[Int] ~~> fetchUserFromDb

Compositor /> basically implies the same idea but for types A / B / C ... Z.


By tradition, kudos to awesome contributors: @jenshaase, @imliar and @suls!

Don't miss a new finch release

NewReleases is sending notifications on new releases.