Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Finch.io 
Purely Functional REST API 
with Finagle 
Vladimir Kostyukov 
http://vkostyukov.ru
http://github.com/finagle/finch 
2
Finch.io: Quickstart 
1 def hello(name: String) = new Service[HttpRequest, HttpResponse] = { 
2 def apply(req: HttpRequest...
Finch.io Overview 
• Composable Endpoints 
• Composable Microservices 
• Request Reader 
• Response Builder 
• JSON 
• OAu...
Endpoints 
1 val a = new Endpoint[HttpRequest, HttpResponse] { 
2 def route = { 
3 case Method.Get -> Root / "bob" => Redi...
Composing services & endpoints 
1 val ab: Filter[A, C, B, C] = ??? 
2 val bc: Endpoint[B, C] = ??? 
3 val cd: Service[C, D...
Case Study: Feedbacks Endpoint 
1 object Feedback extends Endpoint[OAuth2Request[OAuthUser], JsonResponse] { 
2 def route ...
Params (Reader Monad) 
1 val user = for { 
2 name <- RequiredParam("name") 
3 age <- RequiredIntParam("age") 
4 city <- Op...
Case Study: Pagination 
1 val pagination = { 
2 val outerLimit = Config[Int]("limit", 15) 
3 
4 for { 
5 offset <- Optiona...
Multi-Value Params 
1 val reader = for { 
2 a <- RequiredIntParams("a") 
3 b <- RequiredIntParams("b") 
4 } yield (a, b) 
...
Validation 
1 val adult = for { 
2 u <- user 
3 _ <- ValidationRule("age", "should be greater then 18") { user.age >= 18 }...
Responses 
1 // an empty response with status 200 
2 val a = Ok() 
3 
4 // 'plain/text' response with status 404 
5 val b ...
JSON 
1 // a : { 
2 // b : 10, 
3 // c : 20, 
4 // d : 30 
5 // } 
6 val a = JsonObject("a.b" -> 10, "a.c" -> 20, "a.d" ->...
Basic Auth 
1 object ProtectedUser extends Endpoint[HttpRequest, HttpResponse] { 
2 def route = { 
3 case Method.Get -> Ro...
Further Steps 
• Lightweight in-memory caching 
• Better JSON 
15
References 
§ http://twitter.github.io/finagle/ 
! 
§ https://github.com/finagle/finch 
! 
§ https://github.com/finagle/fi...
Stay Finagled! 
! 
And drop your feedbacks to 
@vkostyukov 
17
Upcoming SlideShare
Loading in …5
×

Finch.io - Purely Functional REST API with Finagle

6,548 views

Published on

https://github.com/finagle/finch

Published in: Technology
  • If you are looking for customer-oriented academic and research paper writing service try ⇒⇒⇒ WRITE-MY-PAPER.net ⇐⇐⇐ liked them A LOTTT Really nice solutions for the last-day papers
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Follow the link, new dating source: ❤❤❤ http://bit.ly/2u6xbL5 ❤❤❤
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Dating for everyone is here: ❤❤❤ http://bit.ly/2u6xbL5 ❤❤❤
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Finch.io - Purely Functional REST API with Finagle

  1. 1. Finch.io Purely Functional REST API with Finagle Vladimir Kostyukov http://vkostyukov.ru
  2. 2. http://github.com/finagle/finch 2
  3. 3. Finch.io: Quickstart 1 def hello(name: String) = new Service[HttpRequest, HttpResponse] = { 2 def apply(req: HttpRequest) = for { 3 title <- OptionalParam("title")(req) 4 } yield Ok(s"Hello, ${title.getOrElse("")} $name!") 5 } 6 7 val endpoint = new Endpoint[HttpRequest, HttpResponse] { 8 def route = { 9 // routes requests like '/hello/Bob?title=Mr.' 10 case Method.Get -> Root / "hello" / name => hello(name) 11 } 12 } 3
  4. 4. Finch.io Overview • Composable Endpoints • Composable Microservices • Request Reader • Response Builder • JSON • OAuth2, Basic Auth 4
  5. 5. Endpoints 1 val a = new Endpoint[HttpRequest, HttpResponse] { 2 def route = { 3 case Method.Get -> Root / "bob" => Redirect("/users/bob") 4 case Method.Get -> Root / "users" / Long(id) => GetUser(id) 5 } 6 } 7 8 val b = new Endpoint[HttpRequest, HttpResponse] { 9 def route = { 10 case Method.Get -> Root / "tickets" => GetTickets 11 } 12 } 13 14 val c: Endpoint[HttpRequest, HttpResponse] = a orElse b 15 val d: Service[HttpRequest, HttpResponse] = c.toService 5
  6. 6. Composing services & endpoints 1 val ab: Filter[A, C, B, C] = ??? 2 val bc: Endpoint[B, C] = ??? 3 val cd: Service[C, D] = ??? 4 5 val ad: Endpoint[A, D] = ab ! bc ! cd 6
  7. 7. Case Study: Feedbacks Endpoint 1 object Feedback extends Endpoint[OAuth2Request[OAuthUser], JsonResponse] { 2 def route = { 3 case Method.Get -> Root / "users" / Long(id) / "feedbacks" => 4 GetUserFeedbacks(id) ! 5 JoinInnerArrays("attachments") ! 6 TakeAll 7 8 case Method.Put -> Root / "orders" / Long(id) / "feedback" => 9 ByUserId(MakeSureUserCanPutOrderFeedback(_, id)) ! 10 MakeSureThereIsNoOrderFeedbacks(id) ! 11 MakeSureOrderIsCompleted(id) ! 12 PutOrderFeedback(id) ! 13 ByLocation(UpdateServiceRating) ! 14 ByLocation(SendFeedbackSubmittedMail) ! 15 ByLocation(GetFeedback) ! 16 TakeFirst 17 } 18 } 7
  8. 8. Params (Reader Monad) 1 val user = for { 2 name <- RequiredParam("name") 3 age <- RequiredIntParam("age") 4 city <- OptionalParam("city") 5 } yield User(name, age, city.getOrElse("Novosibirsk")) 6 7 val service = new Service[HttpRequest, JsonResponse] { 8 def apply(req: HttpRequest) = for { 9 u <- user(req) 10 } yield JsonObject( 11 "name" -> u.name, 12 "age" -> u.age, 13 "city" -> u.city 14 ) 15 } 16 17 val u: Future[User] = user(request) handle { 18 case e: ParamNotFound => BadRequest(e.param) 19 } 8
  9. 9. Case Study: Pagination 1 val pagination = { 2 val outerLimit = Config[Int]("limit", 15) 3 4 for { 5 offset <- OptionalIntParam("offset") 6 limit <- OptionalIntParam("limit") 7 } yield ( 8 offset.getOrElse(0), 9 math.min(limit.getOrElse(outerLimit), outerLimit) 10 ) 11 } 12 13 val a = new Service[HttpRequest, HttpResponse] { 14 def apply(req: HttpRequest) = for { 15 (offset, limit) <- pagination(req) 16 } yield Ok(s"offset $offset, limit $limit") 17 } 9
  10. 10. Multi-Value Params 1 val reader = for { 2 a <- RequiredIntParams("a") 3 b <- RequiredIntParams("b") 4 } yield (a, b) 5 6 // request("a=1,2,3&b=4&b=5") 7 val (a, b): (List[Int], List[Int]) = reader(request) 8 // a = List(1, 2, 3) 9 // b = List(4, 5) 10
  11. 11. Validation 1 val adult = for { 2 u <- user 3 _ <- ValidationRule("age", "should be greater then 18") { user.age >= 18 } 4 } yield u 5 6 val user: Future[User] = adult(request) handle { 7 case e: ParamNotFound => 8 BadRequest(JsonObject("param" -> e.param)) 9 case e: ValidationFailed => 10 BadRequest(JsonObject("param" -> e.param, "rule" -> e.rule)) 11 } 11
  12. 12. Responses 1 // an empty response with status 200 2 val a = Ok() 3 4 // 'plain/text' response with status 404 5 val b = NotFound("body") 6 7 // 'application/json' response with status 201 8 val c = Created(JsonObject("id" -> 42)) 9 10 // 'plain/text' response of status 403 with custom header 11 val d = Forbidden.withHeaders("Some-Header-A" -> "a")("plain") 12
  13. 13. JSON 1 // a : { 2 // b : 10, 3 // c : 20, 4 // d : 30 5 // } 6 val a = JsonObject("a.b" -> 10, "a.c" -> 20, "a.d" -> 30) 7 8 // a : { 9 // a : 100, 10 // b : 200 11 // } 12 val b = JsonObject("a.a" -> 100, "a.b" -> 200) 13 14 // a : { 15 // a : 100 16 // b : 200, 17 // c : 20, 18 // d : 30 19 // } 20 val c = JsonObject.mergeRight(a, b) 13
  14. 14. Basic Auth 1 object ProtectedUser extends Endpoint[HttpRequest, HttpResponse] { 2 def route = { 3 case Method.Get -> Root / "users" => 4 BasicallyAuthorize("user", "password") ! 5 GetUsers 6 } 7 } 14
  15. 15. Further Steps • Lightweight in-memory caching • Better JSON 15
  16. 16. References § http://twitter.github.io/finagle/ ! § https://github.com/finagle/finch ! § https://github.com/finagle/finagle-oauth2 16
  17. 17. Stay Finagled! ! And drop your feedbacks to @vkostyukov 17

×