Async WebParts and >=>
Every Suave handler is a WebPart: a function from HttpContext to an async optional context.
type WebPart = HttpContext -> Async<HttpContext option>Async computation expressions
You can write WebParts with F# async workflows:
open Suave
open Suave.Successful
let sleep (milliseconds : int) message : WebPart =
fun ctx -> async {
do! Async.Sleep milliseconds
return! OK message ctx
}Kleisli composition (>=>)
The >=> operator chains two WebParts. If the left-hand side returns None, the right-hand side is never run (short-circuit). If it returns Some ctx, that context is passed to the next WebPart.
open Suave
open Suave.Filters
open Suave.Operators
open Suave.Successful
let app =
path "/hello"
>=> GET
>=> OK "Hello"This is the same idea as railway-oriented programming: success continues, failure stops the chain.
choose
choose tries WebParts in order until one succeeds:
open Suave
open Suave.Filters
open Suave.Operators
open Suave.Successful
let app = choose [
path "/a" >=> OK "A"
path "/b" >=> OK "B"
RequestErrors.NOT_FOUND "Not found"
]WebParts are values — evaluate per request
A WebPart closes over values captured when it was constructed. If you bake in DateTime.Now at definition time, every request sees that same timestamp. Wrap dynamic work in a function applied to the context (or use context / request / warbler) so it runs per request. See the FAQ.
Next: operators, composition, or a recipe.