Dealing with HttpClient and HttpRequestMessage in F#

I simply cannot explain how many times I had to read the documentation in order to remember how to do HTTP calls using HttpClient and HttpRequestMessage. Let’s put an end to this madness now!

Defining a Base Address

This is useful if you intend to use the same HttpClient to make multiple calls to the same API. If that’s the case, do not remove the trailing-slash as it will cause problems when concatenating endpoint paths!

let client = new HttpClient()
client.BaseAddress <- "https://example.com/api/"

// joining our endpoint path
let uri = Uri(client.BaseAddress, "login")

GET Request

In order to make GET requests, you need to setup an HttpRequestMessage instance with the desired method and your endpoint Uri.

let message = new HttpRequestMessage(HttpMethod.Get, uri)
// send request
use! response = client.SendAsync(message)
// read json
let! body = response.Content.ReadFromJsonAsync<T>()

Sending JSON on a POST request

This process is a bit more involved as you need to serialize the JSON into a string before sending the message. Fortunately, we have everything we need without relying on external libraries!

let credentials =
    { Username = "gluer"
      Password = "secret" }

// serialize the credentials object into a string
let json =
    let serialized =
        credentials |> JsonSerializer.Serialize

    new StringContent(serialized, Encoding.UTF8, "application/json")

// prepare the request with a POST method and our Uri
let message = new HttpRequestMessage(HttpMethod.Post, uri)
message.Content <- json

// send request
use! response = state.Client.SendAsync(message)

// read json response
let! body = response.Content.ReadFromJsonAsync<T>()

Error handling

Unfortunately, by default, there is no F#-friendly way of handling errors on HTTP calls. However, the good news is that dealing with them is not difficult either!

type ResponseError =
    | NetworkError of Exception
    | TimeoutError of Exception
    | Unknown of Exception
//...
try
    use! responseMessage = httpClient.SendAsync(message)
    let! body = responseMessage.Content.ReadFromJsonAsync<T>()
    return Ok body
with
| :? HttpRequestException as ex ->
    return Error(NetworkError ex)
| :? TaskCanceledException as ex ->
    return Error(TimeoutError ex)
| ex ->
    return  Error(Unknown ex)

Articles from blogs I follow around the net

The four tenets of SOA revisited

Twenty years after. In the January 2004 issue of MSDN Magazine you can find an article by Don Box titled A Guide to Developing and Running Connected Systems with Indigo. Buried within the (now dated) discussion of the technology…

via ploeh blog March 4, 2024

Building a demo of the Bleichenbacher RSA attack in Rust

Recently while reading Real-World Cryptography, I got nerd sniped1 by the mention of Bleichenbacher's attack on RSA. This is cool, how does it work? I had to understand, and to understand something, I usually have to build it. Well, friends, that is what…

via ntietz.com blog March 4, 2024

How to unbreak Dolphin on SteamOS after the QT6 update

A recent update to Dolphin made it switch to QT6. This makes it crash with this error or something like it: dolphin-emu: symbol lookup error: dolphin-emu: undefined symbol: _Zls6QDebugRK11QDockWidget, version Qt_6 This is fix…

via Xe Iaso's blog March 3, 2024

Generated by openring