My agentic slop goes here. Not intended for anyone else!
at main 5.2 kB view raw
1(** Centralized error handling for the Requests library *) 2 3let src = Logs.Src.create "requests.error" ~doc:"HTTP Request Errors" 4module Log = (val Logs.src_log src : Logs.LOG) 5 6(** {1 Exception Types} *) 7 8exception Timeout 9exception TooManyRedirects of { url: string; count: int; max: int } 10exception ConnectionError of string 11exception HTTPError of { 12 url: string; 13 status: int; 14 reason: string; 15 body: string option; 16 headers: Headers.t 17} 18exception AuthenticationError of string 19exception SSLError of string 20exception ProxyError of string 21exception EncodingError of string 22exception InvalidURL of string 23exception InvalidRequest of string 24 25(** {1 Error Type} *) 26 27type t = [ 28 | `Timeout 29 | `TooManyRedirects of string * int * int (* url, count, max *) 30 | `ConnectionError of string 31 | `HTTPError of string * int * string * string option * Headers.t (* url, status, reason, body, headers *) 32 | `AuthenticationError of string 33 | `SSLError of string 34 | `ProxyError of string 35 | `EncodingError of string 36 | `InvalidURL of string 37 | `InvalidRequest of string 38 | `UnknownError of string 39] 40 41(** {1 Conversion Functions} *) 42 43let of_exn = function 44 | Timeout -> Some `Timeout 45 | TooManyRedirects { url; count; max } -> 46 Some (`TooManyRedirects (url, count, max)) 47 | ConnectionError msg -> Some (`ConnectionError msg) 48 | HTTPError { url; status; reason; body; headers } -> 49 Some (`HTTPError (url, status, reason, body, headers)) 50 | AuthenticationError msg -> Some (`AuthenticationError msg) 51 | SSLError msg -> Some (`SSLError msg) 52 | ProxyError msg -> Some (`ProxyError msg) 53 | EncodingError msg -> Some (`EncodingError msg) 54 | InvalidURL msg -> Some (`InvalidURL msg) 55 | InvalidRequest msg -> Some (`InvalidRequest msg) 56 | _ -> None 57 58let to_exn = function 59 | `Timeout -> Timeout 60 | `TooManyRedirects (url, count, max) -> 61 TooManyRedirects { url; count; max } 62 | `ConnectionError msg -> ConnectionError msg 63 | `HTTPError (url, status, reason, body, headers) -> 64 HTTPError { url; status; reason; body; headers } 65 | `AuthenticationError msg -> AuthenticationError msg 66 | `SSLError msg -> SSLError msg 67 | `ProxyError msg -> ProxyError msg 68 | `EncodingError msg -> EncodingError msg 69 | `InvalidURL msg -> InvalidURL msg 70 | `InvalidRequest msg -> InvalidRequest msg 71 | `UnknownError msg -> Failure msg 72 73let raise error = Stdlib.raise (to_exn error) 74 75(** {1 Combinators} *) 76 77let catch f = 78 try Ok (f ()) 79 with 80 | exn -> 81 match of_exn exn with 82 | Some err -> Error err 83 | None -> Error (`UnknownError (Printexc.to_string exn)) 84 85let catch_async f = catch f (* In Eio, regular catch works for async too *) 86 87let map f = function 88 | Ok x -> Ok (f x) 89 | Error e -> Error e 90 91let bind f = function 92 | Ok x -> f x 93 | Error e -> Error e 94 95let both a b = 96 match a, b with 97 | Ok x, Ok y -> Ok (x, y) 98 | Error e, _ -> Error e 99 | _, Error e -> Error e 100 101let get_exn = function 102 | Ok x -> x 103 | Error e -> raise e 104 105let get_or ~default = function 106 | Ok x -> x 107 | Error _ -> default 108 109let is_retryable = function 110 | `Timeout -> true 111 | `ConnectionError _ -> true 112 | `HTTPError (_, status, _, _, _) -> Status.is_retryable (Status.of_int status) 113 | `SSLError _ -> true 114 | `ProxyError _ -> true 115 | _ -> false 116 117let is_client_error = function 118 | `HTTPError (_, status, _, _, _) -> Status.is_client_error (Status.of_int status) 119 | `AuthenticationError _ 120 | `InvalidURL _ 121 | `InvalidRequest _ -> true 122 | _ -> false 123 124let is_server_error = function 125 | `HTTPError (_, status, _, _, _) -> Status.is_server_error (Status.of_int status) 126 | _ -> false 127 128 129(** {1 Pretty Printing} *) 130 131let pp ppf = function 132 | `Timeout -> 133 Format.fprintf ppf "@[<2>Request Timeout:@ The request timed out@]" 134 | `TooManyRedirects (url, count, max) -> 135 Format.fprintf ppf "@[<2>Too Many Redirects:@ Exceeded maximum redirects (%d/%d) for URL: %s@]" 136 count max url 137 | `ConnectionError msg -> 138 Format.fprintf ppf "@[<2>Connection Error:@ %s@]" msg 139 | `HTTPError (url, status, reason, body, _headers) -> 140 Format.fprintf ppf "@[<v>@[<2>HTTP Error %d (%s):@ URL: %s@]" status reason url; 141 Option.iter (fun b -> 142 Format.fprintf ppf "@,@[<2>Response Body:@ %s@]" b 143 ) body; 144 Format.fprintf ppf "@]" 145 | `AuthenticationError msg -> 146 Format.fprintf ppf "@[<2>Authentication Error:@ %s@]" msg 147 | `SSLError msg -> 148 Format.fprintf ppf "@[<2>SSL/TLS Error:@ %s@]" msg 149 | `ProxyError msg -> 150 Format.fprintf ppf "@[<2>Proxy Error:@ %s@]" msg 151 | `EncodingError msg -> 152 Format.fprintf ppf "@[<2>Encoding Error:@ %s@]" msg 153 | `InvalidURL msg -> 154 Format.fprintf ppf "@[<2>Invalid URL:@ %s@]" msg 155 | `InvalidRequest msg -> 156 Format.fprintf ppf "@[<2>Invalid Request:@ %s@]" msg 157 | `UnknownError msg -> 158 Format.fprintf ppf "@[<2>Unknown Error:@ %s@]" msg 159 160let pp_exn ppf exn = 161 match of_exn exn with 162 | Some err -> pp ppf err 163 | None -> Format.fprintf ppf "%s" (Printexc.to_string exn) 164 165let to_string error = 166 Format.asprintf "%a" pp error 167 168(** {1 Syntax Module} *) 169 170module Syntax = struct 171 let ( let* ) x f = bind f x 172 let ( let+ ) x f = map f x 173 let ( and* ) = both 174end