Skip to main content David Edelstein's Blog

🦙
🦙

Suave.IO vdir to run choose routes relative to a path

Published: 2014-07-15
dave@edelsteinautomotive.com
David Edelstein
let vdir (s : String) choose_list (ctx : HttpContext) = 
  if ctx.request.url.StartsWith(s)
  then  
    let us = 
      if ctx.user_state.ContainsKey("original_url")
      then ctx.user_state
      else ctx.user_state.Add("original_url", ctx.request.url)
    let new_req = { ctx with request={ctx.request with url=ctx.request.url.Substring(s.Length)} ; user_state = us } in
      choose choose_list new_req
  else None
      
let subapp = 
  vdir "/sub"  [ 
    url "/abc" >>= OK "subapp abc route"
    warbler(fun {request=req ; user_state=us} -> OK ( sprintf "subapp - url %s - original url %A" req.url us))
  ]      
      
  

Now when subapp is loaded inside an application’s choose chain, if /sub/xyz is visited, the browser will print:
subapp - url /xyz - original url map [(“original_url”, “/sub/xyz”)]

Is this an abuse of the user_state list maintained by Suave?

As an alternative, we can define the vdir function to take a WebPart:

let vdir (s : String) (app : WebPart) (ctx : HttpContext) = 
  if ctx.request.url.StartsWith(s)
  then  
    let us = 
      if ctx.user_state.ContainsKey("original_url")
      then ctx.user_state
      else ctx.user_state.Add("original_url", ctx.request.url)
    let new_req = { ctx with request={ctx.request with url=ctx.request.url.Substring(s.Length)} ; user_state = us } in
      app new_req
  else None

let subapp = 
  vdir "/sub" <| choose [ 
    url "/abc" >>= OK "def"
    warbler(fun {request=req ; user_state=us} -> OK ( sprintf "subapp with choose - url %s - original url %A" req.url us))
  ]