A batteries included HTTP/1.1 client in OCaml
at main 132 lines 4.5 kB view raw
1(*--------------------------------------------------------------------------- 2 Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 SPDX-License-Identifier: ISC 4 ---------------------------------------------------------------------------*) 5 6(** HTTP Proxy Configuration 7 8 Per RFC 9110 Section 3.7 and Section 7.3.2: 9 A proxy is a message-forwarding agent chosen by the client, 10 usually configured via local rules. 11 12 {2 Usage} 13 14 Create a proxy configuration: 15 {[ 16 let proxy = Proxy.http ~port:8080 "proxy.example.com" 17 18 (* With authentication *) 19 let proxy = Proxy.http 20 ~port:8080 21 ~auth:(Auth.basic ~username:"user" ~password:"pass") 22 "proxy.example.com" 23 24 (* With bypass list *) 25 let proxy = Proxy.http 26 ~no_proxy:["localhost"; "*.internal.example.com"] 27 "proxy.example.com" 28 ]} 29 30 Read from environment variables: 31 {[ 32 match Proxy.from_env () with 33 | Some proxy -> (* use proxy *) 34 | None -> (* no proxy configured *) 35 ]} *) 36 37(** Log source for proxy operations *) 38val src : Logs.Src.t 39 40(** {1 Proxy Types} *) 41 42(** Proxy protocol type *) 43type proxy_type = 44 | HTTP (** HTTP proxy (CONNECT for HTTPS, absolute-URI for HTTP) *) 45 | SOCKS5 (** SOCKS5 proxy (RFC 1928) - future extension *) 46 47(** Proxy configuration *) 48type config = { 49 host : string; (** Proxy server hostname *) 50 port : int; (** Proxy server port (default: 8080) *) 51 proxy_type : proxy_type; 52 auth : Auth.t option; (** Proxy authentication (Proxy-Authorization) *) 53 no_proxy : string list; (** Hosts/patterns to bypass proxy *) 54} 55 56(** {1 Configuration Constructors} *) 57 58val http : ?port:int -> ?auth:Auth.t -> ?no_proxy:string list -> string -> config 59(** [http ?port ?auth ?no_proxy host] creates an HTTP proxy configuration. 60 61 @param port Proxy port (default: 8080) 62 @param auth Proxy authentication credentials 63 @param no_proxy List of hosts/patterns to bypass the proxy. 64 Supports wildcards like [*.example.com] to match [foo.example.com]. 65 @param host Proxy server hostname *) 66 67val socks5 : ?port:int -> ?auth:Auth.t -> ?no_proxy:string list -> string -> config 68(** [socks5 ?port ?auth ?no_proxy host] creates a SOCKS5 proxy configuration. 69 70 {b Note:} SOCKS5 support is not yet implemented. This function creates 71 the configuration type for future use. 72 73 @param port Proxy port (default: 1080) 74 @param auth Proxy authentication credentials 75 @param no_proxy List of hosts/patterns to bypass the proxy 76 @param host Proxy server hostname *) 77 78(** {1 Configuration Utilities} *) 79 80val should_bypass : config -> string -> bool 81(** [should_bypass config url] returns [true] if [url] should bypass 82 the proxy based on the [no_proxy] list. 83 84 Matching rules: 85 - Exact hostname match (case-insensitive) 86 - Wildcard prefix match: [*.example.com] matches [foo.example.com] 87 - [localhost] and [127.0.0.1] match by default if in no_proxy list *) 88 89val host_port : config -> string * int 90(** [host_port config] returns the proxy host and port as a tuple. *) 91 92val validate_supported : config -> unit 93(** [validate_supported config] checks that the proxy type is currently supported. 94 @raise Error.Proxy_error if SOCKS5 is requested (not yet implemented) *) 95 96(** {1 Environment Variable Support} *) 97 98val from_env : unit -> config option 99(** [from_env ()] reads proxy configuration from environment variables. 100 101 Checks the following variables (in order of preference): 102 - [HTTP_PROXY] / [http_proxy] 103 - [HTTPS_PROXY] / [https_proxy] 104 - [ALL_PROXY] / [all_proxy] 105 - [NO_PROXY] / [no_proxy] (comma-separated list of bypass patterns) 106 107 Returns [None] if no proxy is configured. 108 109 URL format: [http://[user:pass@]host[:port]] 110 111 Example environment: 112 {[ 113 HTTP_PROXY=http://user:pass@proxy.example.com:8080 114 NO_PROXY=localhost,*.internal.example.com,.example.org 115 ]} *) 116 117val from_env_for_url : string -> config option 118(** [from_env_for_url url] reads proxy configuration appropriate for [url]. 119 120 - Uses [HTTPS_PROXY] for HTTPS URLs 121 - Uses [HTTP_PROXY] for HTTP URLs 122 - Falls back to [ALL_PROXY] 123 - Returns [None] if the URL matches [NO_PROXY] patterns *) 124 125(** {1 Pretty Printing} *) 126 127val pp_proxy_type : Format.formatter -> proxy_type -> unit 128(** Pretty printer for proxy type *) 129 130val pp_config : Format.formatter -> config -> unit 131(** Pretty printer for proxy configuration. 132 Note: Authentication credentials are redacted. *)