嵌套 Suave WebPart

Nesting Suave WebPart

我第一次接触 Suave,显然有些东西我不明白。 我想要实现的是实现一个简单的 Rest API:

现在为了简单起见,我只关注 GET 方法。

我的非常基本代码在这里:

[<AutoOpen>]
module RestFul =    

    let JSON v =     
        let jsonSerializerSettings = new JsonSerializerSettings()
        jsonSerializerSettings.ContractResolver <- new CamelCasePropertyNamesContractResolver()

        JsonConvert.SerializeObject(v, jsonSerializerSettings)
        |> OK 
        >=> Writers.setMimeType "application/json; charset=utf-8"

    let fromJson<'a> json =
        JsonConvert.DeserializeObject(json, typeof<'a>) :?> 'a    

    let getResourceFromReq<'a> (req : HttpRequest) = 
        let getString rawForm = System.Text.Encoding.UTF8.GetString(rawForm)
        req.rawForm |> getString |> fromJson<'a>

    type RestResource<'a> = {
        GetById : int -> 'a option
        GetPricesById : int -> 'a option
    }

    let rest resource =

        let handleResource requestError = function
            | Some r -> r |> JSON
            | _ -> requestError

        let getResourceById = 
            resource.GetById >> handleResource (NOT_FOUND "Resource not found")

        let getPricesById = 
            resource.GetPricesById >> handleResource (NOT_FOUND "Resource not found")

        choose [
            GET >=> pathScan "/instrument/%d" getResourceById
            GET >=> pathScan "/instrument/%d/prices" getPricesById
        ]


module Main =
    [<EntryPoint>]
    let main argv = 

        let webPart = rest {
                GetById = fun i -> Some i // placeholder
                GetPricesById = fun i -> Some i // placeholder, it'll be a list eventually
            }

        startWebServer defaultConfig webPart
        0

当我以这种方式定义 WebPart 时:

choose [
    GET >=> pathScan "/instrument/%d" getResourceById // Returns the instrument static data
    GET >=> pathScan "/instrument/%d/prices" getPricesById // Returns price list for the instrument
]

然后一切正常。我想知道是否有嵌套网络部件的方法,例如像这样:

// My idea about the code - doesn't compile
choose [
    pathScan "/instrument/%d" getResourceById >=> choose [
        GET // Returns the instrument static data
        GET >=> path "/prices" >=> (somehow refer to the previous id and get prices)  // Returns price list for the instrument
    ]
]

此外 - 因为我正在了解 RestAPIs,所以我的推理可能存在差距。我认为以这种方式嵌套价格端点可以清楚地表明价格被视为一种工具的 属性(如果我错了,请随时纠正我)。

是的,所以访问以前的请求有点反文雅 ;) 我们希望事情能够独立发生,而不管刚刚发生了什么。因此,也许更好的解决这个问题的方法是简单地将价格附加到路径的末尾?

choose [
    GET >=> pathScan "/instrument/%d" getResourceById 
    GET >=> pathScan "/instrument/%d/prices" getPricesById
]