How to consume HttpClient from F#?

2019-04-23 11:19发布

I'm new to F# and stuck in understanding async in F# from the perspective of a C# developer. Say having the following snippet in C#:

var httpClient = new HttpClient();
var response = await httpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
string content = await response.Content.ReadAsStringAsync();

How to write the same in F#?

4条回答
【Aperson】
2楼-- · 2019-04-23 11:44

You can use async:

let readString (url: Uri) = async {
    let httpClient = new HttpClient();
    let! response = httpClient.GetAsync(url) |> Async.AwaitTask
    response.EnsureSuccessStatusCode() |> ignore
    return! response.Content.ReadAsStringAsync() |> Async.AwaitTask
}
查看更多
爷、活的狠高调
3楼-- · 2019-04-23 11:44

Just my two cents. But my understanding is that we should be handling the HttpRequestException when using EnsureSuccessStatusCode().

Below is the start of a module wrapping HttpClient that will buffer the response of a URL into a string and safely wrap in a Result<'a, 'b> for improved fault tolerance.

module Http =
    open System    
    open System.Net.Http

    let getStringAsync url =
        async {
            let httpClient = new HttpClient() 
            // This can be easily be made into a HttpClientFactory.Create() call
            // if you're using >= netcore2.1

            try 
                use! resp = httpClient.GetAsync(Uri(url), HttpCompletionOption.ResponseHeadersRead) |> Async.AwaitTask                       
                resp.EnsureSuccessStatusCode |> ignore

                let! str = resp.Content.ReadAsStringAsync() |> Async.AwaitTask
                return Ok str
            with
            | :? HttpRequestException as ex -> return ex.Message |> Error
        }
查看更多
Lonely孤独者°
4楼-- · 2019-04-23 11:56

Here is a function that should do what you're looking for (note that you'll have to wrap the code in an asynchronous computation expression in order to use the let! syntax):

let getAsync (url:string) = 
    async {
        let httpClient = new System.Net.Http.HttpClient()
        let! response = httpClient.GetAsync(url) |> Async.AwaitTask
        response.EnsureSuccessStatusCode () |> ignore
        let! content = response.Content.ReadAsStringAsync() |> Async.AwaitTask
        return content
    }
查看更多
Evening l夕情丶
5楼-- · 2019-04-23 11:57

You'll want to at least read and be aware of the established patterns in Http.fs if you're doing anything with HttpClient in F#.

[See comments] TL;DR ... but Beware the Share. As noted by @pimbrouwers, it should be noted that you don't necessarily have to then use it though - subsetting and/or evolving your own set of helpers in your context can lead you to a better fitting abstraction (and bring you the benefits of the learning on the way).

To this point: It's considered idiomatic practice in F# to keep rarely used and/or overly specific helpers in a non-central location.

查看更多
登录 后发表回答