Pudu programming language
Menu
Package

@chrismichaelps / pudu-lang-httpclient

Named HTTP clients for Pudu: a client factory, delegating handlers, pooled keep-alive connections, handler lifetimes, logging, and resilience

0.1.1Apache-2.01

InstallClose

AuthorizationTest.pudu

Pudu51 lines3.0 KB

GitHub ↗
1/** @Test.Handlers.Authorization.Suite — credentials added to requests, and refreshed when refused */2module PuduLangHttpClient.Handlers.AuthorizationTest34import Std.Concurrent.Cancel as Cancel5import Std.Io as Io6import Std.Result as Result7import Std.Test as Test8import PuduLangHttpClient.Handler as Handler9import PuduLangHttpClient.Handlers.Authorization as Authorization10import PuduLangHttpClient as HttpClient11import PuduLangHttpClient.Request as Request12import PuduLangHttpClient.Response as Response13import PuduLangHttpClient.Stub as Stub14import PuduLangHttpClient.Utils.Shared as Shared1516/// The status a handler answers around the stub for a request.17fn status(handler: Handler.Handler, stub: &Stub.Stub, request: Request.Request) -> Result[Int, HttpClient.Failure] {18  Result.map(Handler.around(handler, Stub.send(stub))(request, Cancel.token()), |response: Response.Response| response.status.code)19}2021/// Runs the suite.22fn main() -> Int {23  let stub = Stub.create()24  Stub.when(&stub, |request: Request.Request| Request.header(&request, "authorization") == Some("Bearer fresh") || Request.header(&request, "authorization") == Some("Basic dTpw") || Request.header(&request, "authorization") == Some("Own x"), |request: Request.Request| Ok(Response.answer(&request, 200)))25  Stub.when(&stub, |_request: Request.Request| true, |request: Request.Request| Ok(Response.answer(&request, 401)))26  let fetched = Shared.shared([])27  let tokens = fn(refresh: Bool) -> HttpClient.Outcome[Str] {28    Shared.update(&fetched, |seen: Array[Bool]| seen.push(refresh))29    Ok(if refresh { "fresh" } else { "stale" })30  }31  let refreshed = status(Authorization.bearer(tokens), &stub, Request.get("http://a/"))32  let refreshes = Shared.current(&fetched)33  let own = status(Authorization.bearer(tokens), &stub, Request.get("http://a/").withHeader("Authorization", "Own x"))34  let failing = status(Authorization.bearer(|_refresh: Bool| HttpClient.invalid("no token")), &stub, Request.get("http://a/"))35  let basic = status(Authorization.basic("u", "p"), &stub, Request.get("http://a/"))36  let kept = status(Authorization.basic("u", "p"), &stub, Request.get("http://a/").withHeader("authorization", "Own x"))37  let stillRefused = status(Authorization.bearer(|_refresh: Bool| Ok("never")), &stub, Request.get("http://a/"))38  let checks = Test.suite("Handlers.Authorization", &[39      Test.equals("a refused token is fetched again and the request sent once more", &(refreshed, refreshes), &(Ok(200), [false, true])),40      Test.equals("a request carrying its own credentials is left alone", &(own, Shared.current(&fetched).length()), &(Ok(200), 2)),41      Test.equals("a token that cannot be fetched fails the request", &failing, &Err(HttpClient.InvalidRequest("no token"))),42      Test.equals("basic credentials are added unless the request has its own", &(basic, kept), &(Ok(200), Ok(200))),43      Test.equals("a second refusal is answered as it is", &stillRefused, &Ok(401))44    ])45  let ran = Test.run(&checks)46  for failure in Test.failuresOf(&ran) {47    let _reported = Io.writeErrorLine(failure)48  }49  Test.report(&ran)50}51