2017-07-19 55 views
2

我一直在玩第一次Suave,顯然有一些我不明白。 我試圖做到的,是實現一個簡單的REST API:嵌套和藹WebPart

  • 用戶可以獲得有關金融工具的信息
  • 此外,每個儀器具有

價格的列表現在簡單我只關注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 
] 

然後一切工作正常。我想知道是否有辦法嵌套webparts,例如像這樣:

// 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時,我的推理可能存在差距。我認爲,嵌套價格終點就是這樣明確表示價格被認爲是工具的一個屬性(如果我錯了,隨時糾正我)。

+2

這不是它的工作原理。你必須放棄「當前請求」的概念。 Suave沒有這樣的事情。這都是功能組成。 –

回答

4

正確,因此訪問先前的請求是一種反差;我們希望事情能夠獨立發生,而不管發生了什麼。因此,解決這個問題的一種更好的方式可能是將價格追加到路徑的末端?

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

與我目前的解決方案完全相同,正確(即我發佈的和有效的)? 此外 - 感謝解釋什麼被認爲是「反和」。這是我想聽到的。 –

+1

我不認爲他正在嘗試訪問*以前的請求*。更像是嵌套'pathScan'鏈的前一部分。這是一個不止一次出現的功能請求(人們要求某種'subPath' combinator),但現在我無法找到其他功能請求提交的位置。如果我找到它們,我會把它們連起來。但是現在,Suave不提供這個功能。 – rmunn