Skip to content

Instantly share code, notes, and snippets.

@gerardtoconnor
Last active June 23, 2017 18:17
Show Gist options
  • Save gerardtoconnor/a0cfdfa95e0e4fe0bd3902363b56d8da to your computer and use it in GitHub Desktop.
Save gerardtoconnor/a0cfdfa95e0e4fe0bd3902363b56d8da to your computer and use it in GitHub Desktop.
Test format of alternative continuation HttpHandler format to prevent need to warp sync results in async
// Unlike Suave bind format, the idea is that the handlers execute as pre-applied continuations, with the added benefit of
// allowing sync operations to be executed in a handler with no addional and wasteful async/task wrappers as the async/task
// of the subsequent succ/fail Continuation that is called can be returned, passed directly through, unlike bind
open System
open System.Text
open System.Threading.Tasks
open System.Collections.Generic
open Microsoft.AspNetCore.Http
/// a partially applied function such that it only needs HttpContext input to trigger
type Continuation = HttpContext -> Task<HttpContext>
// Signature of any HttpHandler Function, a function of three inputs, a partially applied success Fn, a partially applied fail Fn,
// and lastly, the HttpContext that is applied at runtime to execute
type HttpHandler = Continuation -> Continuation -> HttpContext -> Task<HttpContext>
/// Combines two HttpHandler functions into one....
/// the handler function inputs, success & fail continuation functions, are passed over the 'a' prefix function, and partially applied
/// to the suffix (latter) handler 'b', creating a Continuation function that is then partially applied as the success function of the
/// prefix 'a' handler, such that partially applied 'b' is run if succ fn in 'a' is called, and the original (ultimate & final)
/// succ fn will be passed down the pipeline to the last handler, having been initially sent in at front of function pipeline.
let compose (a : HttpHandler) (b : HttpHandler) =
fun (succ : Continuation) (fail : Continuation) (ctx:HttpContext) ->
let childCont = b succ fail
let parentCont = a childCont fail
parentCont ctx
let (>=>) = compose
/// ---------------------------
/// Default HttpHandlers
/// ---------------------------
/// Iterates through a list of HttpHandler functions, providing a fail function that points
/// to the next item in the list and if nothing successfull, calling fail function it recieved.
let rec choose (handlers : HttpHandler list) =
fun (succ: Continuation) (fail : Continuation) (ctx : HttpContext) ->
match handlers with
| [] -> fail ctx
| handler :: tail ->
let next = choose tail succ fail //if a branch fails, go to next handler in list
handler succ next ctx
// A sync handler that does not create any additinaly tasks but returns task of continuation executions
let route (path : string) : HttpHandler =
fun succ fail ctx -> // <<< clean simple format
if (getPath ctx).Equals path
then succ ctx
else fail ctx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment