SlideShare a Scribd company logo
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) = 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
Finch.io Overview 
• Composable Endpoints 
• Composable Microservices 
• Request Reader 
• Response Builder 
• JSON 
• OAuth2, Basic Auth 
4
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
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
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
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
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
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
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
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
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
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
Further Steps 
• Lightweight in-memory caching 
• Better JSON 
15
References 
§ http://twitter.github.io/finagle/ 
! 
§ https://github.com/finagle/finch 
! 
§ https://github.com/finagle/finagle-oauth2 
16
Stay Finagled! 
! 
And drop your feedbacks to 
@vkostyukov 
17

More Related Content

PDF
Async Microservices with Twitter's Finagle
PDF
Finch + Finagle OAuth2
PPTX
Sharding and Load Balancing in Scala - Twitter's Finagle
PDF
Phoenix + Reactで 社内システムを 密かに作ってる
PDF
Rntb20200805
 
PDF
Webエンジニアから見たiOS5
PDF
React native-firebase startup-mtup
 
PDF
Swift Sequences & Collections
Async Microservices with Twitter's Finagle
Finch + Finagle OAuth2
Sharding and Load Balancing in Scala - Twitter's Finagle
Phoenix + Reactで 社内システムを 密かに作ってる
Rntb20200805
 
Webエンジニアから見たiOS5
React native-firebase startup-mtup
 
Swift Sequences & Collections

What's hot (20)

PDF
Reactive, component 그리고 angular2
PDF
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
PDF
React for Beginners
PDF
Tools for Solving Performance Issues
PDF
Scalaz By Example (An IO Taster) -- PDXScala Meetup Jan 2014
PDF
Talk KVO with rac by Philippe Converset
PDF
Python meetup: coroutines, event loops, and non-blocking I/O
PDF
Testing Backbone applications with Jasmine
PDF
Flamingo Training - Hello World
PDF
PyCon lightning talk on my Toro module for Tornado
PDF
Asynchronous I/O in PHP
PDF
第4回 g* ワークショップ はじめてみよう! Grailsプラグイン
PDF
2016 gunma.web games-and-asm.js
PDF
20151224-games
PDF
Introduction to reactive programming & ReactiveCocoa
PDF
Decoupling Objects With Standard Interfaces
PPTX
Template syntax in Angular 2.0
PPTX
Using Cerberus and PySpark to validate semi-structured datasets
PDF
Practical PHP 5.3
PDF
第3回Grails/Groovy勉強会名古屋「Grails名古屋座談会」
Reactive, component 그리고 angular2
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
React for Beginners
Tools for Solving Performance Issues
Scalaz By Example (An IO Taster) -- PDXScala Meetup Jan 2014
Talk KVO with rac by Philippe Converset
Python meetup: coroutines, event loops, and non-blocking I/O
Testing Backbone applications with Jasmine
Flamingo Training - Hello World
PyCon lightning talk on my Toro module for Tornado
Asynchronous I/O in PHP
第4回 g* ワークショップ はじめてみよう! Grailsプラグイン
2016 gunma.web games-and-asm.js
20151224-games
Introduction to reactive programming & ReactiveCocoa
Decoupling Objects With Standard Interfaces
Template syntax in Angular 2.0
Using Cerberus and PySpark to validate semi-structured datasets
Practical PHP 5.3
第3回Grails/Groovy勉強会名古屋「Grails名古屋座談会」
Ad

Similar to Finch.io - Purely Functional REST API with Finagle (20)

PDF
RESTful API using scalaz (3)
PPTX
Introduction to Finch
PDF
Julio Capote, Twitter
PPTX
Building a Reactive RESTful API with Akka Http & Slick
PDF
Http4s
PPTX
Tools for Making Machine Learning more Reactive
PDF
Event Sourcing and Functional Programming
PDF
Functional Programming & Event Sourcing - a pair made in heaven
PPTX
Concurrent Application Development using Scala
PDF
Finatra v2
PDF
Spray human talks
PDF
[HKOSCon 2020] Build an api service using ktor rapidly
PPT
Play!ng with scala
PDF
Dependency Injection in Functional Programming
PDF
Kotlin : Advanced Tricks - Ubiratan Soares
PDF
ScalaDays Amsterdam - Don't block yourself
PPTX
Android and REST
PDF
Rest with-spray
PDF
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
PDF
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
RESTful API using scalaz (3)
Introduction to Finch
Julio Capote, Twitter
Building a Reactive RESTful API with Akka Http & Slick
Http4s
Tools for Making Machine Learning more Reactive
Event Sourcing and Functional Programming
Functional Programming & Event Sourcing - a pair made in heaven
Concurrent Application Development using Scala
Finatra v2
Spray human talks
[HKOSCon 2020] Build an api service using ktor rapidly
Play!ng with scala
Dependency Injection in Functional Programming
Kotlin : Advanced Tricks - Ubiratan Soares
ScalaDays Amsterdam - Don't block yourself
Android and REST
Rest with-spray
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Ad

Recently uploaded (20)

PDF
Machine learning based COVID-19 study performance prediction
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PDF
Empathic Computing: Creating Shared Understanding
PPTX
Programs and apps: productivity, graphics, security and other tools
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
Approach and Philosophy of On baking technology
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PPTX
MYSQL Presentation for SQL database connectivity
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PDF
NewMind AI Weekly Chronicles - August'25 Week I
PDF
Spectral efficient network and resource selection model in 5G networks
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Machine learning based COVID-19 study performance prediction
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
Empathic Computing: Creating Shared Understanding
Programs and apps: productivity, graphics, security and other tools
Per capita expenditure prediction using model stacking based on satellite ima...
20250228 LYD VKU AI Blended-Learning.pptx
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Chapter 3 Spatial Domain Image Processing.pdf
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Approach and Philosophy of On baking technology
Network Security Unit 5.pdf for BCA BBA.
Building Integrated photovoltaic BIPV_UPV.pdf
MYSQL Presentation for SQL database connectivity
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
NewMind AI Weekly Chronicles - August'25 Week I
Spectral efficient network and resource selection model in 5G networks
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows

Finch.io - Purely Functional REST API with Finagle

  • 1. Finch.io Purely Functional REST API with Finagle Vladimir Kostyukov http://vkostyukov.ru
  • 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. Finch.io Overview • Composable Endpoints • Composable Microservices • Request Reader • Response Builder • JSON • OAuth2, Basic Auth 4
  • 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. Further Steps • Lightweight in-memory caching • Better JSON 15
  • 16. References § http://twitter.github.io/finagle/ ! § https://github.com/finagle/finch ! § https://github.com/finagle/finagle-oauth2 16
  • 17. Stay Finagled! ! And drop your feedbacks to @vkostyukov 17