SlideShare a Scribd company logo
1 of 17
Download to read offline
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

What's hot

Swift Sequences & Collections
Swift Sequences & CollectionsSwift Sequences & Collections
Swift Sequences & CollectionsCocoaHeads France
 
Reactive, component 그리고 angular2
Reactive, component 그리고  angular2Reactive, component 그리고  angular2
Reactive, component 그리고 angular2Jeado Ko
 
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-Tsuyoshi Yamamoto
 
Tools for Solving Performance Issues
Tools for Solving Performance IssuesTools for Solving Performance Issues
Tools for Solving Performance IssuesOdoo
 
Scalaz By Example (An IO Taster) -- PDXScala Meetup Jan 2014
Scalaz By Example (An IO Taster) -- PDXScala Meetup Jan 2014Scalaz By Example (An IO Taster) -- PDXScala Meetup Jan 2014
Scalaz By Example (An IO Taster) -- PDXScala Meetup Jan 2014Susan Potter
 
Talk KVO with rac by Philippe Converset
Talk KVO with rac by Philippe ConversetTalk KVO with rac by Philippe Converset
Talk KVO with rac by Philippe ConversetCocoaHeads France
 
Python meetup: coroutines, event loops, and non-blocking I/O
Python meetup: coroutines, event loops, and non-blocking I/OPython meetup: coroutines, event loops, and non-blocking I/O
Python meetup: coroutines, event loops, and non-blocking I/OBuzzcapture
 
Testing Backbone applications with Jasmine
Testing Backbone applications with JasmineTesting Backbone applications with Jasmine
Testing Backbone applications with JasmineLeon van der Grient
 
Flamingo Training - Hello World
Flamingo Training - Hello WorldFlamingo Training - Hello World
Flamingo Training - Hello Worldi-love-flamingo
 
PyCon lightning talk on my Toro module for Tornado
PyCon lightning talk on my Toro module for TornadoPyCon lightning talk on my Toro module for Tornado
PyCon lightning talk on my Toro module for Tornadoemptysquare
 
Asynchronous I/O in PHP
Asynchronous I/O in PHPAsynchronous I/O in PHP
Asynchronous I/O in PHPThomas Weinert
 
第4回 g* ワークショップ はじめてみよう! Grailsプラグイン
第4回 g* ワークショップ はじめてみよう! Grailsプラグイン第4回 g* ワークショップ はじめてみよう! Grailsプラグイン
第4回 g* ワークショップ はじめてみよう! GrailsプラグインTsuyoshi Yamamoto
 
2016 gunma.web games-and-asm.js
2016 gunma.web games-and-asm.js2016 gunma.web games-and-asm.js
2016 gunma.web games-and-asm.jsNoritada Shimizu
 
Introduction to reactive programming & ReactiveCocoa
Introduction to reactive programming & ReactiveCocoaIntroduction to reactive programming & ReactiveCocoa
Introduction to reactive programming & ReactiveCocoaFlorent Pillet
 
Decoupling Objects With Standard Interfaces
Decoupling Objects With Standard InterfacesDecoupling Objects With Standard Interfaces
Decoupling Objects With Standard InterfacesThomas Weinert
 
Template syntax in Angular 2.0
Template syntax in Angular 2.0Template syntax in Angular 2.0
Template syntax in Angular 2.0Eyal Vardi
 
Using Cerberus and PySpark to validate semi-structured datasets
Using Cerberus and PySpark to validate semi-structured datasetsUsing Cerberus and PySpark to validate semi-structured datasets
Using Cerberus and PySpark to validate semi-structured datasetsBartosz Konieczny
 
Practical PHP 5.3
Practical PHP 5.3Practical PHP 5.3
Practical PHP 5.3Nate Abele
 

What's hot (20)

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

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

Tools for Making Machine Learning more Reactive
Tools for Making Machine Learning more ReactiveTools for Making Machine Learning more Reactive
Tools for Making Machine Learning more ReactiveJeff Smith
 
Bare-knuckle web development
Bare-knuckle web developmentBare-knuckle web development
Bare-knuckle web developmentJohannes Brodwall
 
[WSO2 Integration Summit Madrid 2019] Integration + Ballerina
[WSO2 Integration Summit Madrid 2019] Integration + Ballerina[WSO2 Integration Summit Madrid 2019] Integration + Ballerina
[WSO2 Integration Summit Madrid 2019] Integration + BallerinaWSO2
 
Monitoring Your ISP Using InfluxDB Cloud and Raspberry Pi
Monitoring Your ISP Using InfluxDB Cloud and Raspberry PiMonitoring Your ISP Using InfluxDB Cloud and Raspberry Pi
Monitoring Your ISP Using InfluxDB Cloud and Raspberry PiInfluxData
 
I Phone On Rails
I Phone On RailsI Phone On Rails
I Phone On RailsJohn Wilker
 
Flask and Angular: An approach to build robust platforms
Flask and Angular:  An approach to build robust platformsFlask and Angular:  An approach to build robust platforms
Flask and Angular: An approach to build robust platformsAyush Sharma
 
CouchDB on Android
CouchDB on AndroidCouchDB on Android
CouchDB on AndroidSven Haiges
 
RESTful API 제대로 만들기
RESTful API 제대로 만들기RESTful API 제대로 만들기
RESTful API 제대로 만들기Juwon Kim
 
ContainerDays NYC 2016: "OpenWhisk: A Serverless Computing Platform" (Rodric ...
ContainerDays NYC 2016: "OpenWhisk: A Serverless Computing Platform" (Rodric ...ContainerDays NYC 2016: "OpenWhisk: A Serverless Computing Platform" (Rodric ...
ContainerDays NYC 2016: "OpenWhisk: A Serverless Computing Platform" (Rodric ...DynamicInfraDays
 
Groovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony CodeGroovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony Codestasimus
 
Top 10 F5 iRules to migrate to a modern load balancing platform
Top 10 F5 iRules to migrate to a modern load balancing platformTop 10 F5 iRules to migrate to a modern load balancing platform
Top 10 F5 iRules to migrate to a modern load balancing platformAvi Networks
 
Chaincode Development 區塊鏈鏈碼開發
Chaincode Development 區塊鏈鏈碼開發Chaincode Development 區塊鏈鏈碼開發
Chaincode Development 區塊鏈鏈碼開發HO-HSUN LIN
 
Advanced #2 networking
Advanced #2   networkingAdvanced #2   networking
Advanced #2 networkingVitali Pekelis
 
[JCConf 2020] 用 Kotlin 跨入 Serverless 世代
[JCConf 2020] 用 Kotlin 跨入 Serverless 世代[JCConf 2020] 用 Kotlin 跨入 Serverless 世代
[JCConf 2020] 用 Kotlin 跨入 Serverless 世代Shengyou Fan
 
Rpi python web
Rpi python webRpi python web
Rpi python websewoo lee
 
Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010Ismael Celis
 

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

Tools for Making Machine Learning more Reactive
Tools for Making Machine Learning more ReactiveTools for Making Machine Learning more Reactive
Tools for Making Machine Learning more Reactive
 
Bare-knuckle web development
Bare-knuckle web developmentBare-knuckle web development
Bare-knuckle web development
 
[WSO2 Integration Summit Madrid 2019] Integration + Ballerina
[WSO2 Integration Summit Madrid 2019] Integration + Ballerina[WSO2 Integration Summit Madrid 2019] Integration + Ballerina
[WSO2 Integration Summit Madrid 2019] Integration + Ballerina
 
Monitoring Your ISP Using InfluxDB Cloud and Raspberry Pi
Monitoring Your ISP Using InfluxDB Cloud and Raspberry PiMonitoring Your ISP Using InfluxDB Cloud and Raspberry Pi
Monitoring Your ISP Using InfluxDB Cloud and Raspberry Pi
 
I Phone On Rails
I Phone On RailsI Phone On Rails
I Phone On Rails
 
Flask and Angular: An approach to build robust platforms
Flask and Angular:  An approach to build robust platformsFlask and Angular:  An approach to build robust platforms
Flask and Angular: An approach to build robust platforms
 
CouchDB on Android
CouchDB on AndroidCouchDB on Android
CouchDB on Android
 
RESTful API 제대로 만들기
RESTful API 제대로 만들기RESTful API 제대로 만들기
RESTful API 제대로 만들기
 
ContainerDays NYC 2016: "OpenWhisk: A Serverless Computing Platform" (Rodric ...
ContainerDays NYC 2016: "OpenWhisk: A Serverless Computing Platform" (Rodric ...ContainerDays NYC 2016: "OpenWhisk: A Serverless Computing Platform" (Rodric ...
ContainerDays NYC 2016: "OpenWhisk: A Serverless Computing Platform" (Rodric ...
 
Groovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony CodeGroovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony Code
 
Top 10 F5 iRules to migrate to a modern load balancing platform
Top 10 F5 iRules to migrate to a modern load balancing platformTop 10 F5 iRules to migrate to a modern load balancing platform
Top 10 F5 iRules to migrate to a modern load balancing platform
 
Chaincode Development 區塊鏈鏈碼開發
Chaincode Development 區塊鏈鏈碼開發Chaincode Development 區塊鏈鏈碼開發
Chaincode Development 區塊鏈鏈碼開發
 
Advanced #2 networking
Advanced #2   networkingAdvanced #2   networking
Advanced #2 networking
 
[JCConf 2020] 用 Kotlin 跨入 Serverless 世代
[JCConf 2020] 用 Kotlin 跨入 Serverless 世代[JCConf 2020] 用 Kotlin 跨入 Serverless 世代
[JCConf 2020] 用 Kotlin 跨入 Serverless 世代
 
Rpi python web
Rpi python webRpi python web
Rpi python web
 
Intro to Sail.js
Intro to Sail.jsIntro to Sail.js
Intro to Sail.js
 
Server Side Swift: Vapor
Server Side Swift: VaporServer Side Swift: Vapor
Server Side Swift: Vapor
 
Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010
 
Android dev 3
Android dev 3Android dev 3
Android dev 3
 
Ajax - a quick introduction
Ajax - a quick introductionAjax - a quick introduction
Ajax - a quick introduction
 

Recently uploaded

Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxBkGupta21
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 

Recently uploaded (20)

Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptx
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 

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