Как использовать HttpClient из F #?

Я новичок в F # и застрял в понимании async в F # с точки зрения разработчика С#. Скажем, что в С# следующий фрагмент:

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

Как написать то же самое в F #?

Ответ 1

Вот функция, которая должна делать то, что вы ищете (обратите внимание, что вам придется обернуть код в асинхронном выражении вычисления, чтобы использовать синтаксис let!):

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
    }

Ответ 2

Вы должны хотя бы прочитать и знать установленные шаблоны в Http.fs, если вы что-то делаете с HttpClient в F #.

[См. комментарии] TL; DR... , но остерегайтесь доли. Как отмечает @pimbrouwers, следует отметить, что вам не обязательно использовать его, хотя - поднаборы и/или развитие вашего собственного набора помощников в вашем контексте могут привести вас к более подходящей абстракции (и принести вам преимущества обучения в пути).

К этому моменту: в F # считается идиоматической практикой хранить редко используемых и/или чрезмерно специфичных помощников в нецентральном месте.

Ответ 3

Вы можете использовать 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
}

Ответ 4

Просто мои два цента. Но я понимаю, что мы должны обращаться с HttpRequestException при использовании EnsureSuccessStatusCode().

Ниже приведено начало переноса модуля HttpClient, который буферизует ответ URL-адреса в string и безопасно переносит в Result<'a, 'b> для повышения отказоустойчивости.

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
        }

Ответ 5

Просто используйте FSharp.Control.FusionTasks, и у вас будет четкий синтаксис без |> Async.AwaitTask, как

   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
    }