F#异步HTTP请求 - 解析JSON响应

时间:2017-12-27 15:56:19

标签: swift rest asynchronous f# http-post

我尝试使用以下SELECT MontlyBugetId, Min(Initiator),Min(Stage1),Min(Stage2),Min(Stage3),Min(Stage4),Min(StatusId) FROM yourtable GROUP BY MontlyBugetId 代码段向Firebase发送异步POST请求:特别是以下操作,允许匿名登录:

and a DTO

F#

我称之为:

    let makePostRequest (url : string) (requestBody : string) = 
    let req = WebRequest.CreateHttp url
    req.CookieContainer <- new CookieContainer()
    req.Method <- "POST"
    req.ProtocolVersion <- HttpVersion.Version10
    let postBytes = requestBody |> System.Text.Encoding.ASCII.GetBytes
    req.ContentLength <- postBytes.LongLength
    req.ContentType <- "application/xml; charset=utf-8"
    async{
        use! reqStream = req.GetRequestStreamAsync() |> Async.AwaitTask
        do! reqStream.WriteAsync(postBytes, 0, postBytes.Length) |> Async.AwaitIAsyncResult |> Async.Ignore
        reqStream.Close()
        use! res = req.AsyncGetResponse() 
        use stream = res.GetResponseStream()
        use reader = new StreamReader(stream)
        let! rdata = reader.ReadToEndAsync() |> Async.AwaitTask        
        return rdata
    }

我对 let url = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=XXXXXXXXXXXXXXXXX" let data = "returnSecureToken=true" makePostRequest url data 非常陌生,对此如何运作有点困惑。如何从此请求获取JSON响应?我怎么知道什么时候完成?这会阻塞主线程上的UI吗?我正在做的是翻译下面的Swift代码块:

F#

这里的一切对我都有意义,因为我们有一个完成块,在方法执行完毕后调用它,我们知道 Auth.auth().signInAnonymously(completion: { (user, error) in if let err = error { print(err.localizedDescription) return } }) 变量将包含从服务器获得的响应,它没有多大意义给我在F#。

更新:

根据评论中的建议,我引用了F#Data:HTTP Utilities并创建了以下代码片段:

user

然而,这会产生错误let url = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=XXXXXXXXXXXX" Http.RequestString ( url, headers = [ ContentType HttpContentTypes.Json ], body = TextRequest """ {"returnSecureToken": true} """)

更新2: 我已经解决了以下代码:

The value, namespace, type or module Http is not defined

按照这里的例子:

https://firebase.google.com/docs/reference/rest/auth/#section-sign-in-anonymously

然而,当我在这里调用let fetchUrl callback url (requestBody : string) = let req = WebRequest.Create(Uri(url)) req.Method <- "POST" let postBytes = requestBody |> System.Text.Encoding.ASCII.GetBytes req.ContentLength <- postBytes.LongLength req.ContentType <- "application/json; charset=utf-8" let reqStream = req.GetRequestStream() reqStream.Write(postBytes, 0, postBytes.Length); reqStream.Close() use resp = req.GetResponse() use stream = resp.GetResponseStream() use reader = new IO.StreamReader(stream) callback reader url let myCallback (reader:IO.StreamReader) url = let html = reader.ReadToEnd() let html1000 = html.Substring(0,1000) printfn "Downloaded %s. First 1000 is %s" url html1000 html // return all the html let openLandlord () = let url = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=XXXXXXXXXXXXXXXXXXX" let requestBody = """ {"returnSecureToken": true} """ fetchUrl myCallback url requestBody 函数时:

openLandlord

我收到以下错误:

此表达式应该具有类型uint,但这里有类型字符串。

https://fsharpforfunandprofit.com/posts/fvsc-download/

错误:

  1. 绑定时此点或之前的不完整结构化构造。
  2. 未定义构造函数请求的值。
  3. 成员定义中的意外关键字匹配。
  4. 未定义值,名称空间,类型或模块响应。
  5. 成员定义中发现意外。

1 个答案:

答案 0 :(得分:1)

检查以下代码:

open System
open System.Net
open FSharp.Data

type Response = JsonProvider<""" { "name":"John", "age":94 } """>

[<EntryPoint>]
let main argv =
  let request () =
    async {
      let url = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=XXXXXXXXXXXX"
      return! Http.AsyncRequestString
        ( url,
          headers = [ "Content-Type", HttpContentTypes.Json ],
          body = TextRequest """ {"returnSecureToken": true} """ )
    } |>  Async.Catch
  let result = request ()
               |> Async.RunSynchronously
  match result with
  | Choice1Of2 text -> let json = Response.Parse text
                       printfn "name: %A" json.Name   
  | Choice2Of2 e -> printfn "request failed: %A" e
  0 // return an integer exit code

如果提供的类型不适用于您的设置,这可能有所帮助:https://github.com/Microsoft/visualfsharp/issues/3303

将样本JSON替换为服务所需的内容。