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

问题描述 投票:1回答:1

我正在尝试使用以下F#片段向Firebase发送异步POST请求:特别是以下操作,允许匿名登录:

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

    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

我对F#很新,对于它是如何工作有点困惑。如何从此请求获取JSON响应?我怎么知道什么时候完成?这会阻塞主线程上的UI吗?我正在做的是翻译下面的Swift代码块:

 Auth.auth().signInAnonymously(completion: { (user, error) in

        if let err = error {
            print(err.localizedDescription)
            return
        }

    })

这里的一切对我来说都是有意义的,因为我们有一个完成块,在方法执行完毕后调用它,我们知道user变量将包含从服务器获得的响应,它对我来说在F#中没有多大意义。

更新:

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

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

然而,这会产生错误The value, namespace, type or module Http is not defined

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

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

按照这里的例子:

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

但是当我在这里调用openLandlord函数时:

 override x.ViewDidLoad () =
    base.ViewDidLoad ()
    openLandlord ()

我收到以下错误:

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

enter image description here

错误:

  1. 绑定时此点或之前的不完整结构化构造。
  2. 未定义构造函数请求的值。
  3. 成员定义中的意外关键字匹配。
  4. 未定义值,名称空间,类型或模块响应。
  5. 在成员定义中发现意外。
swift rest asynchronous f# http-post
1个回答
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替换为服务所需的内容。

© www.soinside.com 2019 - 2024. All rights reserved.