SlideShare una empresa de Scribd logo
1 de 39
Descargar para leer sin conexión
Unfiltered Unveiled
The Un-framework
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Whoami
Code/train Scala/Node.js for a living
* Currently @ Gust
* Formerly @ ProQuest Flow
* Formerly @ ProQuest Udini
* Formerly @ Bol.com
* Formerly @ Xebia
* Formerly @ TomTom
* Formerly @ Sun Microsystems
© Wilfred Springer, 2015 | http://www.flotsam.nl/
What are we trying to solve here?
GET / HTTP/1.0 HTTP/1.1 200 OK
Host: nxt.flotsam.nl Date: Mon, 27 April, 2015
Accept: text/html …
Last-Modified: …
ETag: "4ce43…"
Content-Type: text/html
Content-Length: 9636
Server: AmazonS3
Content:
…
© Wilfred Springer, 2015 | http://www.flotsam.nl/
And therefore, we shall have an
∞/insane number of web
frameworks
© Wilfred Springer, 2015 | http://www.flotsam.nl/
HTTP
Stuff => Stuff
© Wilfred Springer, 2015 | http://www.flotsam.nl/
HTTP
Request => Response
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Web Application
Request1 => Response1
Request2 => Response2
Request3 => Response3
Request4 => Response4
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Wait, that rings a bell
… match {
case Request1 => Response1
case Request2 => Response2
case Request3 => Response3
case Request4 => Response4
}
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Pattern matching
def doubleOf(obj: Any) = {
obj match {
case i: Int => i * 2
case s: String => s + s
}
}
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Partial Function
{
case i: Int => i * 2
case s: String => s + s
}
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Partial Function
val doubleOf = PartialFunction[Any, Any] = {
case i: Int => i * 2
case s: String => s + s
}
doubleOf(3) // 6
doubleOf("ha") // haha
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Unfiltered Anatomy
The Intent (Simplified)
type Intent = PartialFunction[HttpRequest, ResponseFunction]
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Unfiltered Anatomy
The Intent
type Intent[A,B] = PartialFunction[
HttpRequest[A], // A: some request representation
ResponseFunction[B] // B: some response representation
]
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Unfiltered Anatomy
The Intent
{
case _ => ResponseString("yay")
}
---------------------------------
GET / => HTTP/1.1 200 OK
Content-Length: 3
Content:
yay
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Unfiltered Anatomy
Binding
import unfiltered.filter
import unfiltered.netty
// Turn it into a Jetty compatible Filter
val plan = filter.Planify(intent)
// Turn it into something Netty compatible
val plan = netty.cycle.Planify(intent)
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Unfiltered Anatomy
Launching
import unfiltered.jetty
import unfiltered.filter
import unfiltered.netty
// Turn it into a Jetty compatible Filter
val plan = filter.Planify(intent)
jetty.Server.http(8080).plan(plan).run()
// Turn it into something Netty compatible
val plan = netty.cycle.Planify(intent)
netty.Server.http(8080).plan(plan).run()
© Wilfred Springer, 2015 | http://www.flotsam.nl/
ResponseFunction
Simplified, and not really true
trait ResponseFunction[-A]
extends HttpResponse[A] => HttpResponse[A]
© Wilfred Springer, 2015 | http://www.flotsam.nl/
ResponseFunction
case … => …
case … => … ~> … ~> …
------------------------------------
Ok Html(…)
NotFound Html5(…)
ResponseString(…) JsonContent
Json(…) TextXmlContent
ResponseWriter(…) Redirect(…)
© Wilfred Springer, 2015 | http://www.flotsam.nl/
ResponseFunction
Ok ~> PlainTextContent ~> ResponseString("foo")
-----------------------------------------------------------
Ok resp.setStatus(SC_OK)
PlainTextContent resp.setContentType("text/plain")
ResponseString("foo") resp.setCharacterEncoding("UTF-8")
val writer = resp.getWriter()
writer.print("foo")
writer.close
© Wilfred Springer, 2015 | http://www.flotsam.nl/
ResponseFunction
Composition using ~>
Ok ~> PlainTextContent ~> ResponseString("foo")
NotFound ~> HtmlContent ~> Html(<html>
<body>Not found</body>
</html>)
Redirect("/index.html")
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Or rather…
Scalate
// index.scaml
!!! 5
%html
%head
%body Not found
// .scala
import unfiltered.scalate.Scalate
Ok ~> HtmlContent ~> Scalate(req, "/index.scaml")
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Matching the HttpRequest
case … => …
case … & … & … =>
GET(…) Accept(…)
POST(…) UserAgent(…)
DELETE(…) Host(…)
PUT(…) IfModifiedSince(…)
Path(…) Referer(…)
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Matching the HttpRequest
Samples
case _ =>
case GET(Path('/index'))
case GET(Path(p)) if p endsWith ".json"
case Path(Seg("give", "it", "to", "me" :: Nil))
case Path("/") & Params(params)
case Accept("application/json")
© Wilfred Springer, 2015 | http://www.flotsam.nl/
It's just extractors, dude
object DotJson {
unapply[A](req: HttpRequest[A]) = req.uri endsWith ".json"
}
case DotJson() => ResponseString("Json!")
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Summary so far
— An Intent is just a partial function
— accepting an HttpRequest,
— producing a ResponseFunction
— … which will in turn produce an HttpResponse
— Matching based on HttpRequest extractors
— Use & to compose HttpRequest extractors
— Use ~> to compose ResponseFunctions
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Upping our game
What else do we need?
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Reusable Composite ResponseFunctions
Don't Repeat Yourself
… => Ok ~> HtmlContent ~> Html(<html><body>text1</body></html>)
… => Ok ~> HtmlContent ~> Html(<html><body>text2</body></html>)
… => Ok ~> HtmlContent ~> Html(<html><body>text2</body></html>)
// vs
case class Html5(text: String)
extends ComposeResponse(
Ok ~> HtmlContent ~> Html(<html><body>{text}</body></html>)
)
… => Html5("text1")
… => Html5("text2")
… => Html5("text3")
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Cross Cutting Concerns
or, how to use Spring AOP
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Cross Cutting Concerns
or, how to use Spring AOP
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Cross Cutting Concerns
How NOT to use Spring AOP
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Cross Cutting Concerns
Kit
In general, a Kit is something that:
— Takes an Intent (but it doesn't have to)
— Produces an Intent (which it always has to)
Anything that produces an Intent should be considered
a Kit
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Cross Cutting Concerns
Authentication
import unfiltered.kit.Auth
def verify(username: String, password: String): Boolean = …
Auth.basic(verify) { | {
case … => … | case … => …
case … => … | case … => …
case … => … | case … => …
} | }
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Cross Cutting Concerns
// Can you tell the issue with this code?
import unfiltered.request._
import unfiltered.response._
val Simple = unfiltered.filter.Planify {
case Path("/") & Accepts.Json(_) =>
JsonContent ~> ResponseString("""{ "response": "Ok" }""")
}
unfiltered.jetty.Server(8080).plan(Simple).run()
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Cross Cutting Concerns
Directives for error handling
import unfiltered.directives._, Directives._
val Smart = unfiltered.filter.Planify { Directive.Intent {
case Path("/") =>
for {
_ <- Accepts.Json
} yield JsonContent ~> ResponseString("""{ "response": "Ok" }""")
} }
unfiltered.jetty.Server(8080).plan(Smart).run()
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Cross Cutting Concerns
Directives for routing
val Sweet = unfiltered.filter.Planify { Directive.Intent.Path {
case "/" =>
for {
_ <- Accepts.Json
} yield JsonContent ~> ResponseString("""{ "response": "Ok" }""")
} }
unfiltered.jetty.Server(8080).plan(Sweet).run()
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Parameter Based Routing
Primitive (never do this)
case Params(ps) if ps contains "name" =>
val name = ps.get("name").head
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Parameter Based Routing
No longer preferred
// Building extractor for name parameter
object Name extends Params.Extract("name", Params.first)
case GET("/") & Name(name) =>
© Wilfred Springer, 2015 | http://www.flotsam.nl/
Parameter Based Routing
Getting it right with Directives and Interpreters
Directive.Intent {
case Path("/") =>
for {
name <- data.as.String ~> required named "name"
} yield ResponseString(name)
}
© Wilfred Springer, 2015 | http://www.flotsam.nl/
© Wilfred Springer, 2015 | http://www.flotsam.nl/

Más contenido relacionado

Similar a Unfiltered Unveiled

Real-Time Python Web: Gevent and Socket.io
Real-Time Python Web: Gevent and Socket.ioReal-Time Python Web: Gevent and Socket.io
Real-Time Python Web: Gevent and Socket.ioRick Copeland
 
Implementing Comet using PHP
Implementing Comet using PHPImplementing Comet using PHP
Implementing Comet using PHPKing Foo
 
Caliburn.micro jump start composite applications for WPF, Silverlight and WP7
Caliburn.micro jump start composite applications for WPF, Silverlight and WP7Caliburn.micro jump start composite applications for WPF, Silverlight and WP7
Caliburn.micro jump start composite applications for WPF, Silverlight and WP7Igor Moochnick
 
Defeating firefox by Muneaki Nishimunea - CODE BLUE 2015
Defeating firefox by Muneaki Nishimunea - CODE BLUE 2015Defeating firefox by Muneaki Nishimunea - CODE BLUE 2015
Defeating firefox by Muneaki Nishimunea - CODE BLUE 2015CODE BLUE
 
[1C1]Service Workers
[1C1]Service Workers[1C1]Service Workers
[1C1]Service WorkersNAVER D2
 
Webcast: Asynchronous Programming Demystified
Webcast: Asynchronous Programming DemystifiedWebcast: Asynchronous Programming Demystified
Webcast: Asynchronous Programming DemystifiedSerge Baranovsky
 
Angular 4 The new Http Client Module
Angular 4 The new Http Client ModuleAngular 4 The new Http Client Module
Angular 4 The new Http Client Modulearjun singh
 
Ajax to the Moon
Ajax to the MoonAjax to the Moon
Ajax to the Moondavejohnson
 
WordCamp Montreal 2016 WP-API + React with server rendering
WordCamp Montreal 2016  WP-API + React with server renderingWordCamp Montreal 2016  WP-API + React with server rendering
WordCamp Montreal 2016 WP-API + React with server renderingZiad Saab
 
Servlet 3.1 Async I/O
Servlet 3.1 Async I/OServlet 3.1 Async I/O
Servlet 3.1 Async I/OSimone Bordet
 
Phpconf 2013 - Agile Telephony Applications with PAMI and PAGI
Phpconf 2013 - Agile Telephony Applications with PAMI and PAGIPhpconf 2013 - Agile Telephony Applications with PAMI and PAGI
Phpconf 2013 - Agile Telephony Applications with PAMI and PAGIMarcelo Gornstein
 
Building @Anywhere (for TXJS)
Building @Anywhere (for TXJS)Building @Anywhere (for TXJS)
Building @Anywhere (for TXJS)danwrong
 
Tornado web
Tornado webTornado web
Tornado webkurtiss
 
Netty from the trenches
Netty from the trenchesNetty from the trenches
Netty from the trenchesJordi Gerona
 

Similar a Unfiltered Unveiled (20)

- Webexpo 2010
- Webexpo 2010- Webexpo 2010
- Webexpo 2010
 
Real-Time Python Web: Gevent and Socket.io
Real-Time Python Web: Gevent and Socket.ioReal-Time Python Web: Gevent and Socket.io
Real-Time Python Web: Gevent and Socket.io
 
Implementing Comet using PHP
Implementing Comet using PHPImplementing Comet using PHP
Implementing Comet using PHP
 
Caliburn.micro jump start composite applications for WPF, Silverlight and WP7
Caliburn.micro jump start composite applications for WPF, Silverlight and WP7Caliburn.micro jump start composite applications for WPF, Silverlight and WP7
Caliburn.micro jump start composite applications for WPF, Silverlight and WP7
 
Defeating firefox by Muneaki Nishimunea - CODE BLUE 2015
Defeating firefox by Muneaki Nishimunea - CODE BLUE 2015Defeating firefox by Muneaki Nishimunea - CODE BLUE 2015
Defeating firefox by Muneaki Nishimunea - CODE BLUE 2015
 
[1C1]Service Workers
[1C1]Service Workers[1C1]Service Workers
[1C1]Service Workers
 
Expo qa 2016
Expo qa 2016Expo qa 2016
Expo qa 2016
 
Webcast: Asynchronous Programming Demystified
Webcast: Asynchronous Programming DemystifiedWebcast: Asynchronous Programming Demystified
Webcast: Asynchronous Programming Demystified
 
Angular 4 The new Http Client Module
Angular 4 The new Http Client ModuleAngular 4 The new Http Client Module
Angular 4 The new Http Client Module
 
F# on the Server-Side
F# on the Server-SideF# on the Server-Side
F# on the Server-Side
 
Python, do you even async?
Python, do you even async?Python, do you even async?
Python, do you even async?
 
Ajax to the Moon
Ajax to the MoonAjax to the Moon
Ajax to the Moon
 
WordCamp Montreal 2016 WP-API + React with server rendering
WordCamp Montreal 2016  WP-API + React with server renderingWordCamp Montreal 2016  WP-API + React with server rendering
WordCamp Montreal 2016 WP-API + React with server rendering
 
Servlet 3.1 Async I/O
Servlet 3.1 Async I/OServlet 3.1 Async I/O
Servlet 3.1 Async I/O
 
Phpconf 2013 - Agile Telephony Applications with PAMI and PAGI
Phpconf 2013 - Agile Telephony Applications with PAMI and PAGIPhpconf 2013 - Agile Telephony Applications with PAMI and PAGI
Phpconf 2013 - Agile Telephony Applications with PAMI and PAGI
 
Intro to JavaScript
Intro to JavaScriptIntro to JavaScript
Intro to JavaScript
 
Andrew Sutherland Presentation
Andrew Sutherland PresentationAndrew Sutherland Presentation
Andrew Sutherland Presentation
 
Building @Anywhere (for TXJS)
Building @Anywhere (for TXJS)Building @Anywhere (for TXJS)
Building @Anywhere (for TXJS)
 
Tornado web
Tornado webTornado web
Tornado web
 
Netty from the trenches
Netty from the trenchesNetty from the trenches
Netty from the trenches
 

Más de Wilfred Springer (12)

Scala in your organisation
Scala in your organisationScala in your organisation
Scala in your organisation
 
Simplicity
SimplicitySimplicity
Simplicity
 
Unfiltered Unveiled
Unfiltered UnveiledUnfiltered Unveiled
Unfiltered Unveiled
 
Mongo
MongoMongo
Mongo
 
NoSQL
NoSQLNoSQL
NoSQL
 
NoSQL Rollercoaster
NoSQL RollercoasterNoSQL Rollercoaster
NoSQL Rollercoaster
 
Byzantine Generals
Byzantine GeneralsByzantine Generals
Byzantine Generals
 
Eventually Consistent
Eventually ConsistentEventually Consistent
Eventually Consistent
 
Into the Wild
Into the WildInto the Wild
Into the Wild
 
OOPSLA Talk on Preon
OOPSLA Talk on PreonOOPSLA Talk on Preon
OOPSLA Talk on Preon
 
Spring ME JavaOne
Spring ME JavaOneSpring ME JavaOne
Spring ME JavaOne
 
Spring ME
Spring MESpring ME
Spring ME
 

Último

Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...OnePlan Solutions
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfjoe51371421
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfCionsystems
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️anilsa9823
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AIABDERRAOUF MEHENNI
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 

Último (20)

Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdf
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 

Unfiltered Unveiled

  • 1. Unfiltered Unveiled The Un-framework © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 2. Whoami Code/train Scala/Node.js for a living * Currently @ Gust * Formerly @ ProQuest Flow * Formerly @ ProQuest Udini * Formerly @ Bol.com * Formerly @ Xebia * Formerly @ TomTom * Formerly @ Sun Microsystems © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 3. What are we trying to solve here? GET / HTTP/1.0 HTTP/1.1 200 OK Host: nxt.flotsam.nl Date: Mon, 27 April, 2015 Accept: text/html … Last-Modified: … ETag: "4ce43…" Content-Type: text/html Content-Length: 9636 Server: AmazonS3 Content: … © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 4. And therefore, we shall have an ∞/insane number of web frameworks © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 5. HTTP Stuff => Stuff © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 6. HTTP Request => Response © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 7. Web Application Request1 => Response1 Request2 => Response2 Request3 => Response3 Request4 => Response4 © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 8. Wait, that rings a bell … match { case Request1 => Response1 case Request2 => Response2 case Request3 => Response3 case Request4 => Response4 } © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 9. Pattern matching def doubleOf(obj: Any) = { obj match { case i: Int => i * 2 case s: String => s + s } } © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 10. Partial Function { case i: Int => i * 2 case s: String => s + s } © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 11. Partial Function val doubleOf = PartialFunction[Any, Any] = { case i: Int => i * 2 case s: String => s + s } doubleOf(3) // 6 doubleOf("ha") // haha © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 12. Unfiltered Anatomy The Intent (Simplified) type Intent = PartialFunction[HttpRequest, ResponseFunction] © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 13. Unfiltered Anatomy The Intent type Intent[A,B] = PartialFunction[ HttpRequest[A], // A: some request representation ResponseFunction[B] // B: some response representation ] © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 14. Unfiltered Anatomy The Intent { case _ => ResponseString("yay") } --------------------------------- GET / => HTTP/1.1 200 OK Content-Length: 3 Content: yay © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 15. Unfiltered Anatomy Binding import unfiltered.filter import unfiltered.netty // Turn it into a Jetty compatible Filter val plan = filter.Planify(intent) // Turn it into something Netty compatible val plan = netty.cycle.Planify(intent) © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 16. Unfiltered Anatomy Launching import unfiltered.jetty import unfiltered.filter import unfiltered.netty // Turn it into a Jetty compatible Filter val plan = filter.Planify(intent) jetty.Server.http(8080).plan(plan).run() // Turn it into something Netty compatible val plan = netty.cycle.Planify(intent) netty.Server.http(8080).plan(plan).run() © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 17. ResponseFunction Simplified, and not really true trait ResponseFunction[-A] extends HttpResponse[A] => HttpResponse[A] © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 18. ResponseFunction case … => … case … => … ~> … ~> … ------------------------------------ Ok Html(…) NotFound Html5(…) ResponseString(…) JsonContent Json(…) TextXmlContent ResponseWriter(…) Redirect(…) © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 19. ResponseFunction Ok ~> PlainTextContent ~> ResponseString("foo") ----------------------------------------------------------- Ok resp.setStatus(SC_OK) PlainTextContent resp.setContentType("text/plain") ResponseString("foo") resp.setCharacterEncoding("UTF-8") val writer = resp.getWriter() writer.print("foo") writer.close © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 20. ResponseFunction Composition using ~> Ok ~> PlainTextContent ~> ResponseString("foo") NotFound ~> HtmlContent ~> Html(<html> <body>Not found</body> </html>) Redirect("/index.html") © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 21. Or rather… Scalate // index.scaml !!! 5 %html %head %body Not found // .scala import unfiltered.scalate.Scalate Ok ~> HtmlContent ~> Scalate(req, "/index.scaml") © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 22. Matching the HttpRequest case … => … case … & … & … => GET(…) Accept(…) POST(…) UserAgent(…) DELETE(…) Host(…) PUT(…) IfModifiedSince(…) Path(…) Referer(…) © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 23. Matching the HttpRequest Samples case _ => case GET(Path('/index')) case GET(Path(p)) if p endsWith ".json" case Path(Seg("give", "it", "to", "me" :: Nil)) case Path("/") & Params(params) case Accept("application/json") © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 24. It's just extractors, dude object DotJson { unapply[A](req: HttpRequest[A]) = req.uri endsWith ".json" } case DotJson() => ResponseString("Json!") © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 25. Summary so far — An Intent is just a partial function — accepting an HttpRequest, — producing a ResponseFunction — … which will in turn produce an HttpResponse — Matching based on HttpRequest extractors — Use & to compose HttpRequest extractors — Use ~> to compose ResponseFunctions © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 26. Upping our game What else do we need? © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 27. Reusable Composite ResponseFunctions Don't Repeat Yourself … => Ok ~> HtmlContent ~> Html(<html><body>text1</body></html>) … => Ok ~> HtmlContent ~> Html(<html><body>text2</body></html>) … => Ok ~> HtmlContent ~> Html(<html><body>text2</body></html>) // vs case class Html5(text: String) extends ComposeResponse( Ok ~> HtmlContent ~> Html(<html><body>{text}</body></html>) ) … => Html5("text1") … => Html5("text2") … => Html5("text3") © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 28. Cross Cutting Concerns or, how to use Spring AOP © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 29. Cross Cutting Concerns or, how to use Spring AOP © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 30. Cross Cutting Concerns How NOT to use Spring AOP © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 31. Cross Cutting Concerns Kit In general, a Kit is something that: — Takes an Intent (but it doesn't have to) — Produces an Intent (which it always has to) Anything that produces an Intent should be considered a Kit © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 32. Cross Cutting Concerns Authentication import unfiltered.kit.Auth def verify(username: String, password: String): Boolean = … Auth.basic(verify) { | { case … => … | case … => … case … => … | case … => … case … => … | case … => … } | } © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 33. Cross Cutting Concerns // Can you tell the issue with this code? import unfiltered.request._ import unfiltered.response._ val Simple = unfiltered.filter.Planify { case Path("/") & Accepts.Json(_) => JsonContent ~> ResponseString("""{ "response": "Ok" }""") } unfiltered.jetty.Server(8080).plan(Simple).run() © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 34. Cross Cutting Concerns Directives for error handling import unfiltered.directives._, Directives._ val Smart = unfiltered.filter.Planify { Directive.Intent { case Path("/") => for { _ <- Accepts.Json } yield JsonContent ~> ResponseString("""{ "response": "Ok" }""") } } unfiltered.jetty.Server(8080).plan(Smart).run() © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 35. Cross Cutting Concerns Directives for routing val Sweet = unfiltered.filter.Planify { Directive.Intent.Path { case "/" => for { _ <- Accepts.Json } yield JsonContent ~> ResponseString("""{ "response": "Ok" }""") } } unfiltered.jetty.Server(8080).plan(Sweet).run() © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 36. Parameter Based Routing Primitive (never do this) case Params(ps) if ps contains "name" => val name = ps.get("name").head © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 37. Parameter Based Routing No longer preferred // Building extractor for name parameter object Name extends Params.Extract("name", Params.first) case GET("/") & Name(name) => © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 38. Parameter Based Routing Getting it right with Directives and Interpreters Directive.Intent { case Path("/") => for { name <- data.as.String ~> required named "name" } yield ResponseString(name) } © Wilfred Springer, 2015 | http://www.flotsam.nl/
  • 39. © Wilfred Springer, 2015 | http://www.flotsam.nl/