Recipe: Nested / company-scoped routes

Goal: Match /{company}/customers without capturing the whole path in a single %s.

open Suave
open Suave.Filters
open Suave.Operators
open Suave.Successful

let app = choose [
  GET >=> path "/config" >=> OK "global config"
  GET >=> pathScan "/%s/customers" (fun company ->
    OK (sprintf "customers for %s" company))
  GET >=> pathScan "/%s/customers/%d" (fun (company, id) ->
    OK (sprintf "%s customer %d" company id))
  RequestErrors.NOT_FOUND "Not found"
]

Avoid a lone pathScan "/%s" that wraps nested choose with relative path "/customers"—the scan already consumed the full URL. Put the company segment in every format string, or use Router scopes.