嵌套 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
]
我第一次接触 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
]