This project holds a POC code for a Giraffe middleware that extracts the route information, for example, part of the dynamic path defined in routef, and adds it to the request HTTP context object. This way, the next middlewares on the request flow could get this value in case they need it.
The middleware configuration is basically:
open Microsoft.AspNetCore.Http
open Giraffe
/// Extract the dynamic route information and add to the
/// HTTP context object
let extractRouteInfo (args: 'T) : HttpHandler =
fun (next: HttpFunc) (ctx: HttpContext) ->
ctx.Items.Add("routeInfo", args)
next ctx
/// Helper function that extracts the dynamic route information
/// from the HTTP context object
let getRouteInfo<'T> (ctx: HttpContext) : Result<'T, string> =
let routeInfo = ctx.Items.TryGetValue "routeInfo"
match routeInfo with
| true, info -> Ok(info :?> 'T)
| false, _ -> Error "Route info not available"
And to use it:
// Notice that it's used as the first middleware for the dynamic
// routef http handler
routef "/users/%s" Middlewares.extractRouteInfo >=> validateA >=> validateB >=> endpointHandler
// ....
Notice that this middleware is still aligned with the functional paradigm since it’s a pure function. If you want to check a simple alternative that uses an anonymous function just keep reading this README.
# start the server
dotnet run
# on another terminal...
# reach the API endpoints
curl localhost:3000/ping
curl localhost:3000/users/abc
curl localhost:3000/users/abc/123
If you want something more explicit you can use:
// Assuming that only the `validateA' and `endpointHandler' demands
// the dynamic route information
routef "/users/%s" (fun input -> validateA input >=> validateB >=> endpointHandler input)
I personally think this approach is more ugly since it’s more verbose, and the anonymous function is a bad pattern. But for simple scenarios I would probably use it.
You can also use a named function instead of the anonymous one, but it’s less
generic than the extractRouteInfo
middleware. You’d need to have N
implementations depending on the middlewares combination. Another named function
approach would be to receive a sequence of the middlewares and compose it later,
but I think this would make the code more complex, and dissonant from the common
Giraffe middleware composition with >=>
.