1
package io.finch.middleware
2

3
import cats.effect.IO
4
import com.twitter.finagle.Http
5
import com.twitter.finagle.http.{Response, Status}
6
import com.twitter.util.{Await, Time}
7
import io.finch._
8

9
/**
10
  * Small Finch hello world application serving endpoint protected by serious authentication
11
  * where each request & response are also logged and measured.
12
  *
13
  * This is achieved using Kleisli-based middleware together with [[Bootstrap.compile]]
14
  *
15
  * Use the following curl commands to test it:
16
  *
17
  * {{{
18
  *   curl -v -H "Authorization: secret" http://localhost:8081/hello
19
  *   curl -V -H "Authorization: wrong" http://localhost:8081/hello
20
  * }}}
21
  *
22
  * !Disclaimer: most likely you would need to use proper libraries for logging, auth, and metrics
23
  * instead but their use will be quite similar.
24
  */
25
object Main extends App with Endpoint.Module[IO] {
26

27 0
  val helloWorld: Endpoint[IO, String] = get("hello") {
28 0
    Ok("Hello world")
29
  }
30

31
  val auth: Endpoint.Compiled[IO] => Endpoint.Compiled[IO] = compiled => {
32 0
    Endpoint.Compiled[IO] {
33 0
      case req if req.authorization.contains("secret") => compiled(req)
34 0
      case _                                           => IO.pure(Trace.empty -> Right(Response(Status.Unauthorized)))
35
    }
36
  }
37

38
  val logging: Endpoint.Compiled[IO] => Endpoint.Compiled[IO] = compiled => {
39 0
    compiled.tapWithF { (req, res) =>
40 0
      IO(print(s"Request: $req\n")) *> IO(print(s"Response: $res\n")) *> IO.pure(res)
41
    }
42
  }
43

44
  val stats: Endpoint.Compiled[IO] => Endpoint.Compiled[IO] = compiled => {
45 0
    val now = IO(Time.now)
46 0
    Endpoint.Compiled[IO] { req =>
47
      for {
48 0
        start <- now
49 0
        traceAndResponse <- compiled(req)
50 0
        (trace, response) = traceAndResponse
51 0
        stop <- now
52 0
        _ <- IO(print(s"Response time: ${stop.diff(start)}. Trace: $trace\n"))
53 0
      } yield (trace, response)
54
    }
55
  }
56

57 0
  val filters = Function.chain(Seq(stats, logging, auth))
58 0
  val compiled = filters(Bootstrap.serve[Text.Plain](helloWorld).compile)
59

60 0
  Await.ready(Http.server.serve(":8081", Endpoint.toService(compiled)))
61

62
}

Read our documentation on viewing source code .

Loading