joroKr21 on dispatcher-testing-apis
Update finagle-http, finagle-st… Merge pull request #1479 from s… Stop magically converting Twitt… and 17 more (compare)
joroKr21 on master
Update cats-effect to 3.3.12 Merge pull request #1489 from s… (compare)
joroKr21 on master
Update circe-core, circe-generi… Merge pull request #1488 from s… (compare)
joroKr21 on master
Update sbt-wartremover, wartrem… Merge pull request #1487 from s… (compare)
vkostyukov on validated-again
vkostyukov on master
Get rid of RequestItem; rework … (compare)
vkostyukov on validated-again
more fixes (compare)
Reader.fromStream(...).read()
hi, this code:
Bootstrap .serve[Application.Json](helloWorld :+: combos(env))
causes:
no type parameters for method apply: (e: io.finch.Endpoint[FF,E])
io.finch.Bootstrap[FF,io.finch.Endpoint[FF,E] :: io.finch.Endpoint[zio.Task,String] :: shapeless.HNil,io.finch.Application.Json :: io.finch.Text.Plain :: shapeless.HNil]
in class Serve exist so that it can be applied to arguments (io.finch.Endpoint[[+A]zio.ZIO[Any,Throwable,A],models.UserDTO :+: models.CombosDTO :+: shapeless.CNil])
[error] --- because ---
[error] argument expression's type is not compatible with formal parameter type;
[error] found : io.finch.Endpoint[[+A]zio.ZIO[Any,Throwable,A],models.UserDTO :+: models.CombosDTO :+: shapeless.CNil]
[error] required: io.finch.Endpoint[?FF,?E]
[error]
[error] L77: .serve[Application.Json](helloWorld :+: combos(env))
[error] ^
[error] [E2] Main.scala
[error] type mismatch;
[error] found : io.finch.Endpoint[[+A]zio.ZIO[Any,Throwable,A],models.UserDTO :+: models.CombosDTO :+: shapeless.CNil]
[error] required: io.finch.Endpoint[FF,E]
[error] L77: .serve[Application.Json](helloWorld :+: combos(env))
while:
Bootstrap
.serve[Application.Json](combos(env))
.serve[Application.Json](helloWorld)
will compile just fine, obviously some type inference doesn't work...
:+:
usable in my case ? am i doing something wrong ?
Endpoint[zio.Task, X]
I've been building in finch for a couple of week and using the Cookbook and user guide as much as possible. I really liked the idea of composing Endpoints. So I attempted to build one with mapOutputAsync and twitter.util.Futures.
def checkToken: com.twitter.util.Future[TokenInfo] = ???
val authenticated: Endpoint[IO, TokenInfo] = header(Fields.Authorization).mapOutputAsync {
checkToken(header).map(Ok)
}
This does not work since of header
unlike get
there are not Mapper for the future. I found a way via twitter Future to scala Future (form the cookbook with IO.pure, and IO.fromFuture). But I wonder if there is a way to do this without this step. I also tried to use io.catbirds.util but could not find a good way. Ony one have a better solution?
Future
(if it's really required) somewhere on the very edge of the application where the actual I/O happens
@nebulorum there is no simple answer here, especially on "correctness" of abstraction.
Personally I'd prefer to use F[_]
inside the application instead of fixing on a specific monad, would it be Future
, IO
or Task
.
Speaking of Twitter Future, the only "killer feature" comparing to cats.effect.IO
is LocalContext
that is somewhat similar to Java's ThreadLocal and might be quite handy to use. I.e. monix Task
provides similar capabilities.
We use ReaderT[IO, RequestEnv, *]
monad instead to have the same set of capabilities but also keep referential transparency.
Future
outside of your application logic, there is no difference from your app perspective on what happens outside
Endpoint[User
finch
artifacts or the new finchx
artifacts that make use cats effect? If you are using the ones with cats effect you can do something like this https://github.com/finagle/finch/blob/master/examples/src/main/scala/io/finch/middleware/Main.scala#L32
@sentenza are you using the old
finch
artifacts or the newfinchx
artifacts that make use cats effect? If you are using the ones with cats effect you can do something like this https://github.com/finagle/finch/blob/master/examples/src/main/scala/io/finch/middleware/Main.scala#L32
I'm using the new ones (finchx
) so I guess that will solve my problem, but now I'm wondering how exactly I should take advantage of that middleware in my endpoints.
val auth: Endpoint.Compiled[IO] => Endpoint.Compiled[IO] // where should I put the auth middleware?
val authFilter = Function.chain(Seq(auth))
val compiled = filters(Bootstrap.serve[Text.Plain](myEndpoint).compile)
// Endpoint.toService(compiled) ??
Is there any way to directly apply the authFilter
on my endpoints?
myEndpoint
) will be the subject of filtering once it's passed to the function
If you don't like the case I mentioned and don't care about applicative nature of ::
composition and the fact, that all the endpoints in this composition are evaluated to accumulate the errors, you can implement your own endpoint:
val auth: Endpoint[IO, HNil] = new Endpoint { .. } //or just header.mapOutputAsync depending on how you handle auth
And then compose it with those you need to protect:
get("foo" :: "bar" :: auth) { Ok("protected") }
::
composition all the endpoints evaluated unless one of them returns NotMatched
. Since authentication for you is effectful, meaning it returns IO
, you can't return NotMatched
outside of IO
. Therefore, you will have to return Matched
result with failed output IO[Output]
in case of authentication failure. In that case the rest of ::
endpoints in the same composition scope are still evaluated for the sake of error accumulation. Say, you have JSON body to parse, then it'll be checked instead of failing fast. Nevertheless, Ok("protected")
is never evaluated & returned if at least one of the endpoints in the corresponding composition fails with error, so in that context it's safe