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:
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.