Last active
July 16, 2023 02:01
-
-
Save zeejers/5d5974eccfaf5e9e61c7ae3a660f216d to your computer and use it in GitHub Desktop.
F# Api Client Wrapper Using FSharp.Data.Http
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
open FSharp.Data | |
open System | |
open System.Text | |
type HttpRequestConfig = | |
{ url: string option | |
query: (string * string) list option | |
headers: (string * string) seq option | |
method: string option | |
body: HttpRequestBody option | |
timeout: int option } | |
type HttpRequestError = | |
{ Message: string | |
StatusCode: int | |
RequestConfig: HttpRequestConfig } | |
type Client(credentials: Credentials) = | |
let mutable _username = credentials.username | |
let mutable _password = credentials.password | |
let mutable _region = credentials.region | |
member this.logPrefix = $"Client [{_username}]:" | |
member this.apiUrl = | |
match _region with | |
| EU -> regionURL EU | |
| UK -> regionURL UK | |
| CA -> regionURL CA | |
| _ -> regionURL US | |
member this.authHeader = | |
$"{_username}:{_password}" | |
|> Encoding.UTF8.GetBytes | |
|> System.Convert.ToBase64String | |
member this.getHeaders = | |
[ "Content-Type", "application/json"; "Authorization", this.authHeader ] | |
member this.apiRequest | |
( | |
resource: string, | |
httpRequestConfig: HttpRequestConfig | |
) : Async<Result<HttpResponse, HttpRequestError>> = | |
let url = | |
httpRequestConfig.url | |
|> Option.map (fun x -> $"{x}/{resource}") | |
|> Option.defaultValue $"{this.apiUrl}/{resource}" | |
let query = httpRequestConfig.query |> Option.defaultValue [] | |
let httpMethod = httpRequestConfig.method |> Option.defaultValue "GET" | |
let body = httpRequestConfig.body |> Option.defaultValue (TextRequest "") | |
async { | |
try | |
let! res = | |
Http.AsyncRequest( | |
url, | |
headers = this.getHeaders, | |
query = query, | |
httpMethod = httpMethod, | |
body = body | |
) | |
return Ok res | |
with ex -> | |
printfn "%s" ex.Message | |
let response: HttpRequestError = | |
{ StatusCode = 0 | |
Message = ex.Message | |
RequestConfig = httpRequestConfig } | |
return Error response | |
} | |
// === USAGE EXAMPLE === | |
let client = Client(getCredentials args) | |
let requestConfig: HttpRequestConfig = | |
{ url = Some "https://dummyjson.com/users" | |
method = Some "POST" | |
query = Some [ ("Limit", "10"); ("Skip", "5") ] | |
body = None | |
headers = None | |
timeout = None } | |
let response = this.apiRequest ("users", requestConfig) |> Async.RunSynchronously |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I wanted to take a stab at making a pattern for an F# client that simplified my API calls and provided a consistent response interface using Result. This is my work in progress.