Repository F# setup
open System
open System.Net.Http
open System.Threading
open System.Threading.Tasks
open Axial
open Axial.HttpClient
open Axial.PlatformServiceHTTP Clients
This page shows the shortest path from HttpClient boilerplate to a typed, testable HTTP workflow.
A direct HttpClient call mixes four failure channels into exceptions and manual status checks:
// Untracked: exceptions for transport, manual status checks, unchecked parsing.
let! response = client.GetAsync($"https://api.example.com/users/{userId}") |> Async.AwaitTask
response.EnsureSuccessStatusCode() |> ignore
let! body = response.Content.ReadAsStringAsync() |> Async.AwaitTask
let user = parseUser body // throws on bad payloadsThe same call as an Axial workflow:
open Axial.HttpClient
open Axial.HttpClient.DSL
let user =
GET $"https://api.example.com/users/{userId}"
|> bearer token
|> fetchJson decodeUseruser is a Flow<#IHasHttp, HttpError, User>. The URL hole is URL-encoded as one value, the bearer token is
redacted from every plan and error transcript, connection failures, timeouts, unexpected statuses, and decode
failures all arrive as one typed HttpError, and nothing is sent until a Flow runtime runs the workflow.
Two Levels
Axial.HttpClient has two deliberate levels:
- The
HttpandRequestmodules wrap the commonHttpClientoperations with explicit requests, typed errors, and service-based execution. Use them when you want full control over every request field. - The
DSLmodule adds interpolated URL builders (GET $"..."), pipe-friendly configuration, and terminal verbs (fetch,fetchText,fetchJson) for the everyday call that should read as one line.
Both levels build the same immutable HttpRequest value, so they mix freely: start a request with GET $"..."
and finish it with Request.expect [ 200; 404 ] >> Http.sendResult.
Mental Model
Http.get/GET $"..."create an immutableHttpRequest. Construction never performs I/O.Request.*and DSL combinators (query,bearer,timeout,jsonBody,expect) configure it.Http.send,fetch,fetchText, orfetchJsonconvert it toFlow<#IHasHttp, HttpError, _>.- The Flow runtime resolves
IHttpfrom the environment and performs the exchange.
Because the service boundary is one IHttp.Send method, a complete test fake is a few lines, and
Request.plan renders a redacted description of any request without sending it.
Choose A Guide
- Requests: safe interpolated URLs, query parameters, headers, bodies, and secret redaction.
- Responses and errors: response transcripts, typed JSON decoding, and the
HttpErrormodel. - Reliability: per-request timeouts, expected statuses, and transient-failure retries.
- Testing HTTP: fakes, the live
HttpClientservice, and layer composition.

