Skip to content

Instantly share code, notes, and snippets.

@gerardtoconnor
Last active July 13, 2017 07:36
Show Gist options
  • Save gerardtoconnor/94228aaa67a247f6e18772a6f8b7be0f to your computer and use it in GitHub Desktop.
Save gerardtoconnor/94228aaa67a247f6e18772a6f8b7be0f to your computer and use it in GitHub Desktop.
Next Continuation Handler
type HttpHandlerResult = Task<HttpContext option> // same as previous
type HttpCont = HttpContext -> HttpHandlerResult // continuation same as previous HttpHandler
type HttpHandler = HttpCont -> HttpContext -> HttpHandlerResult // (HttpCont -> HttpCont) : Handler now has two input parameters
let compose (handler : HttpHandler) (handler2 : HttpHandler) : HttpHandler =
fun (next:HttpCont) (ctx : HttpContext) ->
// 1. last next will ultimately be a (fun ctx -> Some ctx) but allows to compose / short circuit with continuations
// 2. We can apply next function at load so all handlers have thier next function refs and need only apply ctx on run
let child = handler2 next // suffix child handler(s) take next (Some ctx) success function
let next = handler child // prefix parent handler takes child handler as next continuation function
match ctx.Response.HasStarted with
| true -> task { return Some ctx }
| false -> next ctx
let rec choose (handlers : HttpHandler list) : HttpHandler =
fun next ctx ->
task {
match handlers with
| [] -> return None
| handler :: tail ->
let! result = handler next ctx
match result with
| Some c -> return Some c
| None -> return! choose tail next ctx
}
let httpVerb (verb : string) : HttpHandler =
fun next ctx ->
if ctx.Request.Method.Equals verb
then next ctx // no longer wrapping async ('Some' replaced with 'task')
else task { return None }
let route (path : string) : HttpHandler =
fun next ctx ->
if (getPath ctx).Equals path
then next ctx // no longer wrapping async ('Some' replaced with 'task')
else Task.FromResult None
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment