Skip to content

Commit 689d1fc

Browse files
author
Henrik Kirk
committed
First version of slides - still need some work
1 parent 2c2c797 commit 689d1fc

File tree

1 file changed

+239
-0
lines changed

1 file changed

+239
-0
lines changed

slides/09/giraffe.md

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,247 @@
1515

1616
---
1717

18+
### Web frameworks
19+
20+
* Standalized way of making web resources available
21+
* API
22+
* Content
23+
* Web frameworks for all language
24+
* C#, Java, php, ... Python, js, ...
25+
26+
----
27+
28+
### ASP.NET
29+
30+
* .NET based WebFramework
31+
* made for C#
32+
* Supports a wide range of applications
33+
* Web pages
34+
* MVC
35+
* Web API
36+
* Web Hooks
37+
* Normally runs in the IIS container
38+
39+
----
40+
41+
### Giraffe
42+
43+
* (micro) Web framework build as middleware to ASP.NET Core
44+
* Make use of 'all' build in middlewares
45+
* static file, authentication, authorization, ..
46+
* Built as a Functional framework (which we like)
47+
* Very simple concept
48+
49+
```fsharp
50+
type HttpFuncResult = Task<HttpContext option>
51+
type HttpFunc = HttpContext -> HttpFuncResult
52+
type HttpHandler = HttpFunc -> HttpContext -> HttpFuncResult
53+
```
54+
55+
---
56+
57+
### `HttpHandler`
58+
59+
* Has a bind method (now called compose)
60+
* and a operator (>=>)
61+
* plus some more (as we will see below)
62+
63+
----
64+
65+
### Prebuilt `HttpHandler`s
66+
67+
* using a prebuilt HttpHandler
68+
* e.g. `text`, `json`, `setBody`, `GET`, `POST`, `compose`
69+
70+
```fsharp
71+
let sayHelloWorld : HttpHandler = text "Hello World, from Giraffe"
72+
```
73+
74+
----
75+
76+
### Using `HttpFunc` to create `HttpHandler`
77+
78+
* When you need access to the HttpContext
79+
```fsharp
80+
// type HttpHandler = HttpFunc -> HttpContext -> HttpFuncResult
81+
let todo: Endpoint =
82+
fun next ctx ->
83+
ServerErrors.NOT_IMPLEMENTED "" next ctx
84+
```
85+
* Applying 'next' and 'ctx' to then subsequent handler.
86+
87+
88+
----
89+
90+
### Explicitly handling async operations
91+
92+
```fsharp
93+
let sayHelloWorld : HttpHandler =
94+
fun (next : HttpFunc) (ctx : HttpContext) ->
95+
task {
96+
let! person = ctx.BindJsonAsync<Person>()
97+
let greeting = sprintf "Hello World, from %s" person.Name
98+
return! text greeting next ctx
99+
}
100+
```
101+
102+
----
103+
104+
### Bind implementation
105+
106+
```fsharp
107+
//Note: concept code
108+
let bind (handler : HttpHandler) (handler2 : HttpHandler) =
109+
fun (ctx : HttpHandlerContext) ->
110+
async {
111+
let! result = handler ctx
112+
match result with
113+
| None -> return None
114+
| Some ctx2 ->
115+
match ctx2.HttpContext.Response.HasStarted with
116+
| true -> return Some ctx2
117+
| false -> return! handler2 ctx2
118+
}
119+
```
120+
121+
* Should look much like something we already know from last week.
122+
123+
124+
----
125+
126+
### `Compose`
127+
128+
* Operator (>=>)
129+
* builds on bind, but is an optimzed version
130+
* E.g.
131+
132+
```fsharp
133+
let app = compose (route "/") (Successful.OK "Hello World")
134+
// or
135+
let app = route "/" >=> Successful.OK "Hello World"
136+
```
137+
138+
----
139+
140+
### `Choose`
141+
142+
* HttpHandler
143+
* Iterates throgh multiple HttpHandlers and apply fist that fits
144+
145+
```fsharp
146+
let app =
147+
choose [
148+
route "/foo" >=> text "Foo"
149+
route "/bar" >=> text "Bar"
150+
]
151+
```
152+
153+
----
154+
155+
### `Warbler`
156+
157+
* Used when you don't want to return static content
158+
```fsharp
159+
// ('a -> 'a -> 'b) -> 'a -> 'b
160+
let warbler f a = f a a
161+
```
162+
* To avoid functions be eagerly loaded
163+
```fsharp [7]
164+
// unit -> string
165+
let time() = System.DateTime.Now.ToString()
166+
167+
let App =
168+
choose [
169+
route "/normal" >=> text (time())
170+
route "/warbler" >=> warbler (fun _ -> text (time()))
171+
]
172+
```
173+
174+
---
175+
176+
### Setting up Giraffe
177+
178+
* Install Giraffe nuget package in F# project
179+
* `PM> Install-Package Giraffe`
180+
181+
182+
```fsharp [7-8]
183+
[<EntryPoint>]
184+
let main _ =
185+
Host.CreateDefaultBuilder()
186+
.ConfigureWebHostDefaults(
187+
fun webHostBuilder ->
188+
webHostBuilder
189+
.Configure(configureApp)
190+
.ConfigureServices(configureServices)
191+
|> ignore)
192+
.Build()
193+
.Run()
194+
0
195+
```
196+
197+
----
198+
199+
### Defining Giraffe middlewere
200+
201+
```fsharp
202+
let webApp = ...
203+
204+
let configureApp (app : IApplicationBuilder) =
205+
// Add Giraffe to the ASP.NET Core pipeline
206+
app.UseGiraffe webApp
207+
208+
let configureServices (services : IServiceCollection) =
209+
// Add Giraffe dependencies
210+
services.AddGiraffe() |> ignore
211+
```
212+
213+
----
214+
215+
### Routing
216+
217+
* Is also an `HttpHandler`
218+
* 'route' being the main
219+
* `route '/info' >=> info`
220+
* 'routeCi' - non exact match
221+
* `route '/info` >=> info`
222+
* 'routex' - regex
223+
* `routex '/info(/?)' >=> info`
224+
* ....
225+
226+
----
227+
228+
### Endpoint routing
229+
230+
```fsharp [1, 6]
231+
let endpoints =
232+
[] // a list of enpoints
233+
let configureApp (appBuilder : IApplicationBuilder) =
234+
appBuilder
235+
.UseRouting()
236+
.UseEndpoints(fun e -> e.MapGiraffeEndpoints(endpoints))
237+
|> ignore
238+
```
239+
240+
note:
241+
```fsharp
242+
let endpoints =
243+
[
244+
GET [
245+
route "/" (text "Hello World")
246+
routef "/%s/%i" handler2
247+
routef "/%s/%s/%s/%i" handler3
248+
]
249+
subRoute "/sub" [
250+
// Not specifying a http verb means it will listen to all verbs
251+
route "/test" handler1
252+
]
253+
]
254+
```
18255

19256
----
20257

21258
## References
22259

260+
* [Reasoning behind creating Giraffe](https://dusted.codes/functional-aspnet-core)
261+

0 commit comments

Comments
 (0)