
Authorization.pudu
Pudu40 lines2.0 KB
1/** @Handlers.Authorization.Module — credentials added to requests, and refreshed when refused */2module PuduLangHttpClient.Handlers.Authorization34import Std.Concurrent.Cancel as Cancel5import Std.Http as Http6import PuduLangHttpClient.Domain.Headers as Headers7import PuduLangHttpClient.Handler as Handler8import PuduLangHttpClient as HttpClient9import PuduLangHttpClient.Request as Request10import PuduLangHttpClient.Response as Response1112/** @Handlers.Authorization.Tokens — a bearer token, fetched again when `refresh` is true */13export type Tokens = fn(Bool) -> HttpClient.Outcome[Str]141516const UNAUTHORIZED: Int = 40117181920export fn basic(user: Str, password: Str) -> Handler.Handler { fixed(Http.basicAuth(user, password)) }2122232425export fn bearer(tokens: Tokens) -> Handler.Handler {26 fn(request: Request.Request, token: Cancel.Token, next: Handler.Send) -> HttpClient.Outcome[Response.Response] {27 if Headers.has(&request.headers, "authorization") { return next(request, token) }28 let first = next(request.setHeader("authorization", Http.bearerAuth(tokens(false) ?)), token) ?29 if first.status.code != UNAUTHORIZED { return Ok(first) }30 next(request.setHeader("authorization", Http.bearerAuth(tokens(true) ?)), token)31 }32}333435fn fixed(value: Str) -> Handler.Handler {36 fn(request: Request.Request, token: Cancel.Token, next: Handler.Send) -> HttpClient.Outcome[Response.Response] {37 if Headers.has(&request.headers, "authorization") { next(request, token) } else { next(request.setHeader("authorization", value), token) }38 }39}40