
Proxy.pudu
Pudu62 lines2.8 KB
1/** @HttpClient.Proxy.Module — a forward proxy requests are sent through */2module PuduLangHttpClient.Proxy34import Std.Http as Http5import PuduLangHttpClient.Domain.Uri as Uri67/** @HttpClient.Proxy.Proxy — the proxy's address, its credentials, and the hosts reached directly */8export type Proxy = { address: Str, credentials: Option[(Str, Str)], bypass: Array[Str], bypassOnLocal: Bool }91011const LOCAL_HOSTS: Set[Str] = #{"localhost", "127.0.0.1", "::1"}121314export fn at(address: Str) -> Proxy { Proxy{address: address, credentials: None, bypass: [], bypassOnLocal: false} }151617export fn validate(proxy: &Proxy) -> Array[Str] {18 match Uri.endpointOf(proxy.address) {19 case Some(endpoint) => if endpoint.secure { ["proxy address must be an http address: " + proxy.address] } else { [] }20 case None => ["proxy address must be an absolute http address: " + proxy.address]21 }22}23242526export fn bypasses(proxy: &Proxy, host: Str) -> Bool {27 let lower = host.toLower()28 if proxy.bypassOnLocal && (lower in LOCAL_HOSTS || lower.startsWith("127.") || !lower.contains(".")) { return true }29 for entry in proxy.bypass {30 let wanted = entry.toLower()31 if wanted == lower || (wanted.startsWith("*.") && lower.endsWith(wanted.drop(1))) { return true }32 }33 false34}353637export fn authorization(proxy: &Proxy) -> Option[Str] {38 let (user, password) = proxy.credentials ?39 Some(Http.basicAuth(user, password))40}4142/** @HttpClient.Proxy.Configuring — a proxy changed one decision at a time */43export trait Configuring {44 45 fn withCredentials(self: &Self, user: Str, password: Str) -> Self46 47 fn bypassing(self: &Self, hosts: &Array[Str]) -> Self48 49 fn bypassingLocal(self: &Self) -> Self50}5152impl Configuring for Proxy {53 54 fn withCredentials(self: &Self, user: Str, password: Str) -> Self { Proxy{..*self, credentials: Some((user, password))} }5556 57 fn bypassing(self: &Self, hosts: &Array[Str]) -> Self { Proxy{..*self, bypass: self.bypass.concat(*hosts)} }5859 60 fn bypassingLocal(self: &Self) -> Self { Proxy{..*self, bypassOnLocal: true} }61}62