简体   繁体   中英

How capture a dynamic sub-path like "/COMPANY/rest..." with Suave and nest the routes?

I have several routes that must be grouped by "company", plus some that are valid for all:

/login
/logout
/demo1/customers
/demo1/products

So I try with suave:

let doReqScan action =
     warbler (fun r ->
        LOG.Debug("ROUTE: {route}", r.request.url)
        match r.request |> getCompany with
        | Some(x) ->
            let isAuth, validDb = isValidDb(x)

            if validDb then
                if isAuth then
                    action(r.request) |> _DoSet
                else
                    jSonNoAuth
            else    
                never
        | _ -> never
    )

let doReq(route:string, action) =
    path route >=> doReqScan action  

let appCompany company =
    choose [      
      path "/ws" >=> handShake ws
      GET >=>  choose
        [
          doReq("/customers", (fun r -> queryCustomers(r)))
          pathScan "/customers/%d" (fun the_id -> doReqScan (fun r -> queryCustomer(r, the_id)))
        ]
     ]
let app =
  choose
    [ allow_cors
      pathScan "/%s" (fun company ->
       choose
            [
                appCompany company
                GET >=>  choose
                  [
                    _doReq( "/config", (fun r -> config(r)) )
                  ]
                POST >=> choose
                  [
                    _doReq( "/login", (fun r -> login(r)))
                    _doReq( "/logout", (fun r -> logout(r)))
                  ]
            ]
        )
      GET >=> Files.browseHome
      jSonNotFound
    ]

However the pathScan capture all the url "/demo1/customers" instead of only "/demo1".

If I understand correctly:

  • All common urls are in the form: /something
  • All company urls are in the form: /companyName/something

Then you can try this:

let appCompany company =
    let com x = "/" + company + x
    choose [      
        path (com "/ws") >=> handShake ws
        GET >=> choose [
            doReq(com "/customers", (fun r -> queryCustomers(r)))
            pathScan "/%s/customers/%d" (fun _ the_id -> doReqScan (fun r -> queryCustomer(r, the_id)))
        ]
    ]

let app =
    choose [
        allow_cors
        GET >=> choose [
                    _doReq( "/config", (fun r -> config(r)) )
                ]
        POST >=> choose [
                    _doReq( "/login", (fun r -> login(r)))
                    _doReq( "/logout", (fun r -> logout(r)))
                 ]
        pathScan "/%s/%s" (fun company _ -> appCompany company)
        GET >=> Files.browseHome
        jSonNotFound
    ]

Looking at what is proposed in Giraffe documentation (similar to Suave in spirit). They use a pathScan with all parts at once named subroutef

So it would be something like :

pathScan "/%s/customers" queryCustomers
pathScan "/%s/products" queryProducts
...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM