F#异步HTTP请求-解析JSON响应 [英] F# asynchronous HTTP request - parse JSON response

查看:61
本文介绍了F#异步HTTP请求-解析JSON响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

错误:

  1. 在绑定时或绑定时不完整的结构化构造.
  2. 未定义构造函数请求的值.
  3. 成员定义中的关键字意外匹配.
  4. 未定义值,名称空间,类型或模块Response.
  5. 在成员定义中标识意外.

解决方案

检查以下代码:

 开放系统打开System.Net打开FSharp.Data类型Response = JsonProvider<""{" name:" John," age:94}"">[< EntryPoint>]让main argv =让request()=异步{让url ="https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=XXXXXXXXXXXX"返回!Http.AsyncRequestString(网址,标头= ["Content-Type",HttpContentTypes.Json],正文= TextRequest""{" returnSecureToken:true}"")} |>异步捕获让结果=请求()|>异步运行匹配结果与|Choice1Of2文字->让json = Response.Parse文本printfn名称:%A" json.Name|Choice2Of2 e->printfn请求失败:%A" e0//返回整数退出代码 

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

将示例JSON替换为服务期望的内容.

I'm trying to use the following snippet of F# to send an asynchronous POST request to Firebase: in particular the following operation, which allows for anonymous sign in:

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
    }

I am calling it as follows:

    let url = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=XXXXXXXXXXXXXXXXX"
    let data = "returnSecureToken=true"
    makePostRequest url data

I'm very new to F# and a bit confused as to how this works. How can I obtain the JSON response from this request? How will I know when this is complete? Will this block the UI on the main thread? What I am doing is translating the following block of Swift code:

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

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

    })

Here everything makes sense to me as we have a completion block which gets called after the method is done executing, and we know that the user variable will contain the response obtained from the server, it makes much less sense to me in F#.

UPDATE:

Following the suggestions in the comments, I have referenced F# Data: HTTP Utilities and created the following code snippet:

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

However this produces the error The value, namespace, type or module Http is not defined

UPDATE 2: I have settled for the following code:

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

following the example here:

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

however when I call the openLandlord function here:

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

I get the following error:

This expression was expected to have type uint but here has type string.

Errors:

  1. Incomplete structured construct at or before this point in binding.
  2. The value of constructor request is not defined.
  3. Unexpected keyword match in member definition.
  4. The value, namespace, type or module Response is not defined.
  5. Unexpected identified in member definition.

解决方案

Check the following code:

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

If type provides are not working with your setup, this may help: https://github.com/Microsoft/visualfsharp/issues/3303

Replace sample JSON with what is expected from the service.

这篇关于F#异步HTTP请求-解析JSON响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆