How to consume HttpClient from F#?

后端 未结 5 1782
攒了一身酷
攒了一身酷 2021-02-20 04:13

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#:



        
相关标签:
5条回答
  • 2021-02-20 04:57

    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
            }
    
    0 讨论(0)
  • 2021-02-20 05:11

    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.

    0 讨论(0)
  • 2021-02-20 05:13

    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
        }
    
    0 讨论(0)
  • 2021-02-20 05:13

    Just use FSharp.Control.FusionTasks and you will have clear syntax without |> Async.AwaitTask like

       let httpClient = new System.Net.Http.HttpClient ()
    
       let getAsync (url:string) = 
        async {
            let! response = httpClient.GetAsync url
            response.EnsureSuccessStatusCode () |> ignore
            let! content = response.Content.ReadAsStringAsync ()
            return content
        }
    
    0 讨论(0)
  • 2021-02-20 05:14

    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
    }
    
    0 讨论(0)
提交回复
热议问题