2

我第一次在 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
]

然后一切正常。我想知道是否有嵌套 webpart 的方法,例如:

// 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 时,我的推理可能存在差距。我认为以这种方式嵌套价格端点清楚地表明价格被视为一种工具的属性(如果我错了,请随时纠正我)。

4

1 回答 1

4

是的,所以访问先前的请求是一种反文雅;)我们希望事情能够独立发生,而不管刚刚发生了什么。那么,解决这个问题的一种更好的思考方式可能是简单地将价格附加到路径的尽头?

choose [
    GET >=> pathScan "/instrument/%d" getResourceById 
    GET >=> pathScan "/instrument/%d/prices" getPricesById
]
于 2017-07-19T12:59:52.303 回答