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

PuduLangHttpClient.pudu

Pudu95 lines3.4 KB

GitHub ↗
1/** @HttpClient.Root.Vocabulary — outcomes and failures of HTTP requests */2module PuduLangHttpClient34import PuduLangHttpClient.Constants.Messages as Messages5import PuduLangHttpClient.Utils.Template as Template67/** @HttpClient.Root.Failure — why a request produced no response */8export type Failure9  = InvalidRequest(Str)10  | NameResolution(Str)11  | Connection(Str)12  | SecureConnection(Str)13  | ProxyTunnel(Str)14  | Protocol(Str)15  | ResponseEnded16  | ContentTooLarge(Int)17  | HeadersTooLarge(Int)18  | TooManyRedirects(Int)19  | NotPermitted(Str)20  | VersionUnsupported(Str)21  | TimedOut(Int)22  | Cancelled(Str)23  | Unsuccessful(Int, Str)24  | Unreadable(Str)25  | Rejected(Str)26  | Crashed(Str)2728/** @HttpClient.Root.Outcome — the value or failure of one request */29export type Outcome[T] = Result[T, Failure]3031/// An outcome refusing a request that cannot be sent as written.32export fn invalid[T](reason: Str) -> Outcome[T] { Err(InvalidRequest(reason)) }3334/// Whether repeating the request may succeed where this attempt failed: a broken or refused35/// connection, an unresolved name, a response cut short or malformed, or a timeout.36export fn isTransient(failure: &Failure) -> Bool {37  match failure {38    case NameResolution(_) => true39    case Connection(_) => true40    case ProxyTunnel(_) => true41    case Protocol(_) => true42    case ResponseEnded => true43    case TimedOut(_) => true44    case _ => false45  }46}4748/// Whether the failure is a cancellation.49export fn isCancellation(failure: &Failure) -> Bool {50  match failure {51    case Cancelled(_) => true52    case _ => false53  }54}5556/// Whether the failure is a timeout.57export fn isTimeout(failure: &Failure) -> Bool {58  match failure {59    case TimedOut(_) => true60    case _ => false61  }62}6364/// The status code a failure reports, when it reports one.65export fn statusOf(failure: &Failure) -> Option[Int] {66  match failure {67    case Unsuccessful(code, _) => Some(code)68    case _ => None69  }70}7172/// One sentence saying what went wrong.73export fn describe(failure: &Failure) -> Str {74  match failure {75    case InvalidRequest(reason) => Template.fill(Messages.INVALID_REQUEST, &[reason])76    case NameResolution(reason) => Template.fill(Messages.NAME_RESOLUTION, &[reason])77    case Connection(reason) => Template.fill(Messages.CONNECTION, &[reason])78    case SecureConnection(reason) => Template.fill(Messages.SECURE_CONNECTION, &[reason])79    case ProxyTunnel(reason) => Template.fill(Messages.PROXY_TUNNEL, &[reason])80    case Protocol(reason) => Template.fill(Messages.PROTOCOL, &[reason])81    case ResponseEnded => Messages.RESPONSE_ENDED82    case ContentTooLarge(limit) => Template.fill(Messages.CONTENT_TOO_LARGE, &[show(limit)])83    case HeadersTooLarge(limit) => Template.fill(Messages.HEADERS_TOO_LARGE, &[show(limit)])84    case TooManyRedirects(limit) => Template.fill(Messages.TOO_MANY_REDIRECTS, &[show(limit)])85    case NotPermitted(reason) => Template.fill(Messages.NOT_PERMITTED, &[reason])86    case VersionUnsupported(version) => Template.fill(Messages.VERSION_UNSUPPORTED, &[version])87    case TimedOut(millis) => Template.fill(Messages.TIMED_OUT, &[show(millis)])88    case Cancelled(reason) => Template.fill(Messages.CANCELLED, &[reason])89    case Unsuccessful(code, reason) => Template.fill(Messages.UNSUCCESSFUL, &[show(code), reason])90    case Unreadable(reason) => Template.fill(Messages.UNREADABLE, &[reason])91    case Rejected(reason) => Template.fill(Messages.REJECTED, &[reason])92    case Crashed(reason) => Template.fill(Messages.CRASHED, &[reason])93  }94}95