use std::http::jsonClient fn main = jsonClient() # json client post 'http://localhost:1234/login', username: 'test', password: 'test' # Either -> || ( it.body.accessToken ) # Either |> println # IO () # Without operators fn main = jsonClient() post 'http://localhost:1234/login', username: 'test', password: 'test' map || ( it.body.accessToken ) fold println () # Better: main which returns IO (a Callable?) automatically calls the IO # Also, JsonClient can "login" using various methods, such as a Bearer token use std::http::{jsonClient, bearerToken} fn main = jsonClient( baseUrl: 'http:/localhost:1234', auth: bearerToken || ( post('/login', username: 'test', password: 'test') map || ( it.body.accessToken ) ) ) get '/greeting' map || ( it.body.greeting ) fold println pub int HttpReqOpts { headers: Map } pub int GetOpts : HttpReqOpts pub int HttpClient { baseUrl: String fn get(path: String, opts?: GetOpts): IOEither fn post(path: String, body: Any, opts: PostOpts): IOEither } pub int JsonClient : HttpClient pub int JsonClientOpts { baseUrl: String fn getAuth(#[self] client: JsonClient) -> HttpClientAuth } pub int HttpClientAuth = (reqBuilder: HttpRequest::Builder) -> Void impl : JsonClient { baseUrl: String fld auth: HttpClientAuth ctor (opts: JsonClientOpts) { self.baseUrl = opts.baseUrl self.auth = opts.getAuth(self) } impl fn get(path, opts) = IOEither::of || ( HttpRequest::builder() tap || { url = baseUrl + path method = 'GET' headers = opts?.headers ?: [:] cookies = opts?.cookies ?: [:] auth(self) }() ) } pub fn jsonClient(opts: JsonClientOpts): JsonClient = JsonClientImpl(opts) pub fn bearerToken(tokenGetter: (#[self] client: JsonClient) -> IOEither) { |client: JsonClient| { let token = tokenGetter.hydrate(self: client)().unwrap() |reqBuilder: HttpRequest::Builder| { reqBuilder.headers['Authorization'] = "Bearer $token" } } }