this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

more

+354 -374
+240 -2
stack/requests/lib/client.ml
··· 20 20 ~net 21 21 () = 22 22 (* Create default TLS config if verify_tls is true and no custom config provided *) 23 - let final_tls_config : Tls.Config.client option = 23 + let tls_config = 24 24 match tls_config, verify_tls with 25 25 | Some config, _ -> Some config 26 26 | None, true -> ··· 45 45 max_retries; 46 46 retry_backoff; 47 47 verify_tls; 48 - tls_config = final_tls_config; 48 + tls_config; 49 49 } 50 50 51 51 let default ~clock ~net = ··· 60 60 let retry_backoff t = t.retry_backoff 61 61 let verify_tls t = t.verify_tls 62 62 let tls_config t = t.tls_config 63 + 64 + (* HTTP Request Methods *) 65 + 66 + let src = Logs.Src.create "requests.client" ~doc:"HTTP Request Client" 67 + module Log = (val Logs.src_log src : Logs.LOG) 68 + 69 + (* Helper to get client or use default *) 70 + let get_client client = 71 + match client with 72 + | Some c -> c 73 + | None -> failwith "No client provided" 74 + 75 + (* Convert our Headers.t to Cohttp.Header.t *) 76 + let headers_to_cohttp headers = 77 + Headers.to_list headers 78 + |> Cohttp.Header.of_list 79 + 80 + (* Convert Cohttp.Header.t to our Headers.t *) 81 + let headers_from_cohttp cohttp_headers = 82 + Cohttp.Header.to_list cohttp_headers 83 + |> Headers.of_list 84 + 85 + (* Main request implementation *) 86 + let request ~sw ?client ?headers ?body ?auth ?timeout ?follow_redirects 87 + ?max_redirects ~method_ url = 88 + let client = get_client client in 89 + let start_time = Unix.gettimeofday () in 90 + 91 + Log.info (fun m -> m "Making %s request to %s" (Method.to_string method_) url); 92 + 93 + (* Prepare headers *) 94 + let headers = match headers with 95 + | Some h -> h 96 + | None -> default_headers client 97 + in 98 + 99 + (* Apply auth *) 100 + let headers = match auth with 101 + | Some a -> 102 + Log.debug (fun m -> m "Applying authentication"); 103 + Auth.apply a headers 104 + | None -> headers 105 + in 106 + 107 + (* Add content type from body *) 108 + let headers = match body with 109 + | Some b -> (match Body.content_type b with 110 + | Some mime -> Headers.content_type mime headers 111 + | None -> headers) 112 + | None -> headers 113 + in 114 + 115 + (* Convert to Cohttp types *) 116 + let cohttp_method = 117 + match Method.to_string method_ with 118 + | "GET" -> `GET 119 + | "POST" -> `POST 120 + | "PUT" -> `PUT 121 + | "DELETE" -> `DELETE 122 + | "HEAD" -> `HEAD 123 + | "OPTIONS" -> `OPTIONS 124 + | "PATCH" -> `PATCH 125 + | "CONNECT" -> `CONNECT 126 + | "TRACE" -> `TRACE 127 + | _ -> `GET 128 + in 129 + 130 + let cohttp_headers = headers_to_cohttp headers in 131 + let cohttp_body = match body with 132 + | Some b -> Body.to_cohttp_body b 133 + | None -> None 134 + in 135 + 136 + (* Make request using cohttp-eio *) 137 + let uri = Uri.of_string url in 138 + 139 + (* Create HTTPS handler if TLS is configured *) 140 + let https = match tls_config client with 141 + | None -> 142 + Log.debug (fun m -> m "No TLS configuration"); 143 + None 144 + | Some tls_config -> 145 + Log.debug (fun m -> m "Using TLS configuration"); 146 + let https_fn uri socket = 147 + let host = 148 + Uri.host uri 149 + |> Option.map (fun x -> Domain_name.(host_exn (of_string_exn x))) 150 + in 151 + Tls_eio.client_of_flow ?host tls_config socket 152 + in 153 + Some https_fn 154 + in 155 + 156 + (* Create the client *) 157 + let eio_client = Cohttp_eio.Client.make ~https (net client) in 158 + 159 + (* Apply timeout if specified *) 160 + let make_request () = 161 + Cohttp_eio.Client.call ~sw eio_client cohttp_method uri ~headers:cohttp_headers ?body:cohttp_body 162 + in 163 + 164 + (* Make the actual request with optional timeout *) 165 + let resp, resp_body = 166 + match timeout with 167 + | Some t -> 168 + let timeout_seconds = Timeout.total t in 169 + (match timeout_seconds with 170 + | Some seconds -> 171 + Log.debug (fun m -> m "Setting timeout: %.2f seconds" seconds); 172 + Eio.Time.with_timeout_exn (clock client) seconds make_request 173 + | None -> make_request ()) 174 + | None -> make_request () 175 + in 176 + 177 + let status = Cohttp.Response.status resp |> Cohttp.Code.code_of_status in 178 + let cohttp_resp_headers = Cohttp.Response.headers resp in 179 + let resp_headers = headers_from_cohttp cohttp_resp_headers in 180 + 181 + Log.info (fun m -> m "Received response: status=%d" status); 182 + 183 + (* Handle redirects if enabled *) 184 + let follow_redirects = Option.value follow_redirects ~default:true in 185 + let max_redirects = Option.value max_redirects ~default:10 in 186 + 187 + let final_resp, final_body, final_url = 188 + if follow_redirects && (status >= 300 && status < 400) then 189 + let rec follow_redirect url redirects_left = 190 + if redirects_left <= 0 then begin 191 + Log.err (fun m -> m "Too many redirects (%d) for %s" max_redirects url); 192 + raise (Error.TooManyRedirects { url; count = max_redirects; max = max_redirects }) 193 + end else 194 + (* Get location header from Cohttp headers *) 195 + match Cohttp.Header.get cohttp_resp_headers "location" with 196 + | None -> 197 + Log.debug (fun m -> m "Redirect response missing Location header"); 198 + (resp, resp_body, url) 199 + | Some location -> 200 + Log.info (fun m -> m "Following redirect to %s (%d remaining)" 201 + location redirects_left); 202 + (* Make new request to redirect location *) 203 + let new_uri = Uri.of_string location in 204 + let new_resp, new_body = 205 + Cohttp_eio.Client.call ~sw eio_client cohttp_method new_uri ~headers:cohttp_headers 206 + in 207 + let new_status = Cohttp.Response.status new_resp |> Cohttp.Code.code_of_status in 208 + if new_status >= 300 && new_status < 400 then 209 + follow_redirect location (redirects_left - 1) 210 + else 211 + (new_resp, new_body, location) 212 + in 213 + follow_redirect url max_redirects 214 + else 215 + (resp, resp_body, url) 216 + in 217 + 218 + (* Get final headers *) 219 + let final_headers = 220 + if final_resp == resp then 221 + resp_headers 222 + else 223 + Cohttp.Response.headers final_resp |> headers_from_cohttp 224 + in 225 + 226 + let elapsed = Unix.gettimeofday () -. start_time in 227 + Log.info (fun m -> m "Request completed in %.3f seconds" elapsed); 228 + 229 + Response.make 230 + ~status 231 + ~headers:final_headers 232 + ~body:final_body 233 + ~url:final_url 234 + ~elapsed 235 + 236 + (* Convenience methods *) 237 + let get ~sw ?client ?headers ?auth ?timeout ?follow_redirects ?max_redirects url = 238 + request ~sw ?client ?headers ?auth ?timeout ?follow_redirects ?max_redirects 239 + ~method_:`GET url 240 + 241 + let post ~sw ?client ?headers ?body ?auth ?timeout url = 242 + request ~sw ?client ?headers ?body ?auth ?timeout ~method_:`POST url 243 + 244 + let put ~sw ?client ?headers ?body ?auth ?timeout url = 245 + request ~sw ?client ?headers ?body ?auth ?timeout ~method_:`PUT url 246 + 247 + let delete ~sw ?client ?headers ?auth ?timeout url = 248 + request ~sw ?client ?headers ?auth ?timeout ~method_:`DELETE url 249 + 250 + let head ~sw ?client ?headers ?auth ?timeout url = 251 + request ~sw ?client ?headers ?auth ?timeout ~method_:`HEAD url 252 + 253 + let patch ~sw ?client ?headers ?body ?auth ?timeout url = 254 + request ~sw ?client ?headers ?body ?auth ?timeout ~method_:`PATCH url 255 + 256 + let upload ~sw ?client ?headers ?auth ?timeout ?method_ ?mime ?length 257 + ?on_progress ~source url = 258 + let method_ = Option.value method_ ~default:`POST in 259 + let mime = Option.value mime ~default:Mime.octet_stream in 260 + 261 + (* Wrap source with progress tracking if callback provided *) 262 + let tracked_source = match on_progress with 263 + | None -> source 264 + | Some callback -> 265 + (* For now, progress tracking is not implemented for uploads 266 + due to complexity of wrapping Eio.Flow.source. 267 + This would require creating a custom flow wrapper. *) 268 + let _ = callback in 269 + source 270 + in 271 + 272 + let body = Body.of_stream ?length mime tracked_source in 273 + request ~sw ?client ?headers ~body ?auth ?timeout ~method_ url 274 + 275 + let download ~sw ?client ?headers ?auth ?timeout ?on_progress url ~sink = 276 + let response = get ~sw ?client ?headers ?auth ?timeout url in 277 + 278 + try 279 + (* Get content length for progress tracking *) 280 + let total = Response.content_length response in 281 + 282 + let body = Response.body response in 283 + 284 + (* Stream data to sink with optional progress *) 285 + match on_progress with 286 + | None -> 287 + (* No progress tracking, just copy directly *) 288 + Eio.Flow.copy body sink 289 + | Some progress_fn -> 290 + (* Copy with progress tracking *) 291 + (* We need to intercept the flow to track bytes *) 292 + (* For now, just do a simple copy - proper progress tracking needs flow wrapper *) 293 + progress_fn ~received:0L ~total; 294 + Eio.Flow.copy body sink; 295 + progress_fn ~received:(Option.value total ~default:0L) ~total; 296 + 297 + Response.close response 298 + with e -> 299 + Response.close response; 300 + raise e
+109 -1
stack/requests/lib/client.mli
··· 18 18 val default : clock:'a Eio.Time.clock -> net:'b Eio.Net.t -> ('a Eio.Time.clock, 'b Eio.Net.t) t 19 19 (** Create a client with default configuration *) 20 20 21 - (** Internal accessors - for use by Stream module *) 21 + (** Internal accessors *) 22 22 val clock : ('a,'b) t -> 'a 23 23 val net : ('a,'b) t -> 'b 24 24 val default_headers : ('a,'b) t -> Headers.t ··· 27 27 val retry_backoff : ('a,'b) t -> float 28 28 val verify_tls : ('a,'b) t -> bool 29 29 val tls_config : ('a,'b) t -> Tls.Config.client option 30 + 31 + (** {2 HTTP Request Methods} *) 32 + 33 + val request : 34 + sw:Eio.Switch.t -> 35 + ?client:(_ Eio.Time.clock , _ Eio.Net.t) t -> 36 + ?headers:Headers.t -> 37 + ?body:Body.t -> 38 + ?auth:Auth.t -> 39 + ?timeout:Timeout.t -> 40 + ?follow_redirects:bool -> 41 + ?max_redirects:int -> 42 + method_:Method.t -> 43 + string -> 44 + Response.t 45 + (** Make a streaming request *) 46 + 47 + val get : 48 + sw:Eio.Switch.t -> 49 + ?client:(_ Eio.Time.clock , _ Eio.Net.t) t -> 50 + ?headers:Headers.t -> 51 + ?auth:Auth.t -> 52 + ?timeout:Timeout.t -> 53 + ?follow_redirects:bool -> 54 + ?max_redirects:int -> 55 + string -> 56 + Response.t 57 + (** GET request *) 58 + 59 + val post : 60 + sw:Eio.Switch.t -> 61 + ?client:(_ Eio.Time.clock , _ Eio.Net.t) t -> 62 + ?headers:Headers.t -> 63 + ?body:Body.t -> 64 + ?auth:Auth.t -> 65 + ?timeout:Timeout.t -> 66 + string -> 67 + Response.t 68 + (** POST request *) 69 + 70 + val put : 71 + sw:Eio.Switch.t -> 72 + ?client:(_ Eio.Time.clock , _ Eio.Net.t) t -> 73 + ?headers:Headers.t -> 74 + ?body:Body.t -> 75 + ?auth:Auth.t -> 76 + ?timeout:Timeout.t -> 77 + string -> 78 + Response.t 79 + (** PUT request *) 80 + 81 + val delete : 82 + sw:Eio.Switch.t -> 83 + ?client:(_ Eio.Time.clock , _ Eio.Net.t) t -> 84 + ?headers:Headers.t -> 85 + ?auth:Auth.t -> 86 + ?timeout:Timeout.t -> 87 + string -> 88 + Response.t 89 + (** DELETE request *) 90 + 91 + val head : 92 + sw:Eio.Switch.t -> 93 + ?client:(_ Eio.Time.clock , _ Eio.Net.t) t -> 94 + ?headers:Headers.t -> 95 + ?auth:Auth.t -> 96 + ?timeout:Timeout.t -> 97 + string -> 98 + Response.t 99 + (** HEAD request *) 100 + 101 + val patch : 102 + sw:Eio.Switch.t -> 103 + ?client:(_ Eio.Time.clock , _ Eio.Net.t) t -> 104 + ?headers:Headers.t -> 105 + ?body:Body.t -> 106 + ?auth:Auth.t -> 107 + ?timeout:Timeout.t -> 108 + string -> 109 + Response.t 110 + (** PATCH request *) 111 + 112 + val upload : 113 + sw:Eio.Switch.t -> 114 + ?client:(_ Eio.Time.clock , _ Eio.Net.t) t -> 115 + ?headers:Headers.t -> 116 + ?auth:Auth.t -> 117 + ?timeout:Timeout.t -> 118 + ?method_:Method.t -> 119 + ?mime:Mime.t -> 120 + ?length:int64 -> 121 + ?on_progress:(sent:int64 -> total:int64 option -> unit) -> 122 + source:Eio.Flow.source_ty Eio.Resource.t -> 123 + string -> 124 + Response.t 125 + (** Upload from stream *) 126 + 127 + val download : 128 + sw:Eio.Switch.t -> 129 + ?client:(_ Eio.Time.clock , _ Eio.Net.t) t -> 130 + ?headers:Headers.t -> 131 + ?auth:Auth.t -> 132 + ?timeout:Timeout.t -> 133 + ?on_progress:(received:int64 -> total:int64 option -> unit) -> 134 + string -> 135 + sink:Eio.Flow.sink_ty Eio.Resource.t -> 136 + unit 137 + (** Download to stream *)
-1
stack/requests/lib/requests.ml
··· 11 11 module Client = Client 12 12 module Status = Status 13 13 module Error = Error 14 - module Stream = Stream 15 14 module Session = Session 16 15 module Cookie_jar = Cookie_jar 17 16 module Retry = Retry
-3
stack/requests/lib/requests.mli
··· 13 13 module Client = Client 14 14 module Error = Error 15 15 16 - (** {1 Streaming Interface} *) 17 - 18 - module Stream = Stream 19 16 20 17 (** {1 Session Interface} *) 21 18
+5 -19
stack/requests/lib/session.ml
··· 135 135 (** {1 Configuration Management} *) 136 136 137 137 let set_default_header t key value = 138 - Mutex.lock t.mutex; 139 138 t.default_headers <- Headers.set key value t.default_headers; 140 - Mutex.unlock t.mutex; 141 139 Log.debug (fun m -> m "Set default header %s: %s" key value) 142 140 143 141 let remove_default_header t key = 144 - Mutex.lock t.mutex; 145 142 t.default_headers <- Headers.remove key t.default_headers; 146 - Mutex.unlock t.mutex; 147 143 Log.debug (fun m -> m "Removed default header %s" key) 148 144 149 145 let set_auth t auth = 150 - Mutex.lock t.mutex; 151 146 t.auth <- Some auth; 152 - Mutex.unlock t.mutex; 153 147 Log.debug (fun m -> m "Set session authentication") 154 148 155 149 let clear_auth t = 156 - Mutex.lock t.mutex; 157 150 t.auth <- None; 158 - Mutex.unlock t.mutex; 159 151 Log.debug (fun m -> m "Cleared session authentication") 160 152 161 153 let set_timeout t timeout = 162 - Mutex.lock t.mutex; 163 - t.timeout <- timeout; 164 - Mutex.unlock t.mutex 154 + t.timeout <- timeout 165 155 166 156 let set_retry t retry = 167 - Mutex.lock t.mutex; 168 - t.retry <- Some retry; 169 - Mutex.unlock t.mutex 157 + t.retry <- Some retry 170 158 171 159 let disable_retry t = 172 - Mutex.lock t.mutex; 173 - t.retry <- None; 174 - Mutex.unlock t.mutex 160 + t.retry <- None 175 161 176 162 (** {1 Cookie Management} *) 177 163 ··· 205 191 206 192 (* Make the actual request with retry if configured *) 207 193 let make_request () = 208 - (* Use Stream.request to make the actual HTTP request *) 209 - Stream.request ~sw:t.sw ~client:t.client 194 + (* Use Client.request to make the actual HTTP request *) 195 + Client.request ~sw:t.sw ~client:t.client 210 196 ~headers ~method_ ?body ?auth ~timeout 211 197 ~follow_redirects ~max_redirects url 212 198 in
-239
stack/requests/lib/stream.ml
··· 1 - let src = Logs.Src.create "requests.stream" ~doc:"HTTP Request Stream" 2 - module Log = (val Logs.src_log src : Logs.LOG) 3 - 4 - (* Import Error module exceptions *) 5 - 6 - (* Helper to get client or use default *) 7 - let get_client client = 8 - match client with 9 - | Some c -> c 10 - | None -> failwith "No client provided" 11 - 12 - (* Helper to get client or use default *) 13 - 14 - (* Convert our Headers.t to Cohttp.Header.t *) 15 - let headers_to_cohttp headers = 16 - Headers.to_list headers 17 - |> Cohttp.Header.of_list 18 - 19 - (* Convert Cohttp.Header.t to our Headers.t *) 20 - let headers_from_cohttp cohttp_headers = 21 - Cohttp.Header.to_list cohttp_headers 22 - |> Headers.of_list 23 - 24 - (* Main request implementation *) 25 - let request ~sw ?client ?headers ?body ?auth ?timeout ?follow_redirects 26 - ?max_redirects ~method_ url = 27 - let client = get_client client in 28 - let start_time = Unix.gettimeofday () in 29 - 30 - Log.info (fun m -> m "Making %s request to %s" (Method.to_string method_) url); 31 - 32 - (* Prepare headers *) 33 - let headers = match headers with 34 - | Some h -> h 35 - | None -> Client.default_headers client 36 - in 37 - 38 - (* Apply auth *) 39 - let headers = match auth with 40 - | Some a -> 41 - Log.debug (fun m -> m "Applying authentication"); 42 - Auth.apply a headers 43 - | None -> headers 44 - in 45 - 46 - (* Add content type from body *) 47 - let headers = match body with 48 - | Some b -> (match Body.content_type b with 49 - | Some mime -> Headers.content_type mime headers 50 - | None -> headers) 51 - | None -> headers 52 - in 53 - 54 - (* Convert to Cohttp types *) 55 - let cohttp_method = 56 - match Method.to_string method_ with 57 - | "GET" -> `GET 58 - | "POST" -> `POST 59 - | "PUT" -> `PUT 60 - | "DELETE" -> `DELETE 61 - | "HEAD" -> `HEAD 62 - | "OPTIONS" -> `OPTIONS 63 - | "PATCH" -> `PATCH 64 - | "CONNECT" -> `CONNECT 65 - | "TRACE" -> `TRACE 66 - | _ -> `GET 67 - in 68 - 69 - let cohttp_headers = headers_to_cohttp headers in 70 - let cohttp_body = match body with 71 - | Some b -> Body.to_cohttp_body b 72 - | None -> None 73 - in 74 - 75 - (* Make request using cohttp-eio *) 76 - let uri = Uri.of_string url in 77 - 78 - (* Create HTTPS handler if TLS is configured *) 79 - let https = match Client.tls_config client with 80 - | None -> 81 - Log.debug (fun m -> m "No TLS configuration"); 82 - None 83 - | Some tls_config -> 84 - Log.debug (fun m -> m "Using TLS configuration"); 85 - let https_fn uri socket = 86 - let host = 87 - Uri.host uri 88 - |> Option.map (fun x -> Domain_name.(host_exn (of_string_exn x))) 89 - in 90 - Tls_eio.client_of_flow ?host tls_config socket 91 - in 92 - Some https_fn 93 - in 94 - 95 - (* Create the client *) 96 - let eio_client = Cohttp_eio.Client.make ~https (Client.net client) in 97 - 98 - (* Apply timeout if specified *) 99 - let make_request () = 100 - Cohttp_eio.Client.call ~sw eio_client cohttp_method uri ~headers:cohttp_headers ?body:cohttp_body 101 - in 102 - 103 - (* Make the actual request with optional timeout *) 104 - let resp, resp_body = 105 - match timeout with 106 - | Some t -> 107 - let timeout_seconds = Timeout.total t in 108 - (match timeout_seconds with 109 - | Some seconds -> 110 - Log.debug (fun m -> m "Setting timeout: %.2f seconds" seconds); 111 - Eio.Time.with_timeout_exn (Client.clock client) seconds make_request 112 - | None -> make_request ()) 113 - | None -> make_request () 114 - in 115 - 116 - let status = Cohttp.Response.status resp |> Cohttp.Code.code_of_status in 117 - let cohttp_resp_headers = Cohttp.Response.headers resp in 118 - let resp_headers = headers_from_cohttp cohttp_resp_headers in 119 - 120 - Log.info (fun m -> m "Received response: status=%d" status); 121 - 122 - (* Handle redirects if enabled *) 123 - let follow_redirects = Option.value follow_redirects ~default:true in 124 - let max_redirects = Option.value max_redirects ~default:10 in 125 - 126 - let final_resp, final_body, final_url = 127 - if follow_redirects && (status >= 300 && status < 400) then 128 - let rec follow_redirect url redirects_left = 129 - if redirects_left <= 0 then begin 130 - Log.err (fun m -> m "Too many redirects (%d) for %s" max_redirects url); 131 - raise (Error.TooManyRedirects { url; count = max_redirects; max = max_redirects }) 132 - end else 133 - (* Get location header from Cohttp headers *) 134 - match Cohttp.Header.get cohttp_resp_headers "location" with 135 - | None -> 136 - Log.debug (fun m -> m "Redirect response missing Location header"); 137 - (resp, resp_body, url) 138 - | Some location -> 139 - Log.info (fun m -> m "Following redirect to %s (%d remaining)" 140 - location redirects_left); 141 - (* Make new request to redirect location *) 142 - let new_uri = Uri.of_string location in 143 - let new_resp, new_body = 144 - Cohttp_eio.Client.call ~sw eio_client cohttp_method new_uri ~headers:cohttp_headers 145 - in 146 - let new_status = Cohttp.Response.status new_resp |> Cohttp.Code.code_of_status in 147 - if new_status >= 300 && new_status < 400 then 148 - follow_redirect location (redirects_left - 1) 149 - else 150 - (new_resp, new_body, location) 151 - in 152 - follow_redirect url max_redirects 153 - else 154 - (resp, resp_body, url) 155 - in 156 - 157 - (* Get final headers *) 158 - let final_headers = 159 - if final_resp == resp then 160 - resp_headers 161 - else 162 - Cohttp.Response.headers final_resp |> headers_from_cohttp 163 - in 164 - 165 - let elapsed = Unix.gettimeofday () -. start_time in 166 - Log.info (fun m -> m "Request completed in %.3f seconds" elapsed); 167 - 168 - Response.make 169 - ~status 170 - ~headers:final_headers 171 - ~body:final_body 172 - ~url:final_url 173 - ~elapsed 174 - 175 - (* Convenience methods *) 176 - let get ~sw ?client ?headers ?auth ?timeout ?follow_redirects ?max_redirects url = 177 - request ~sw ?client ?headers ?auth ?timeout ?follow_redirects ?max_redirects 178 - ~method_:`GET url 179 - 180 - let post ~sw ?client ?headers ?body ?auth ?timeout url = 181 - request ~sw ?client ?headers ?body ?auth ?timeout ~method_:`POST url 182 - 183 - let put ~sw ?client ?headers ?body ?auth ?timeout url = 184 - request ~sw ?client ?headers ?body ?auth ?timeout ~method_:`PUT url 185 - 186 - let delete ~sw ?client ?headers ?auth ?timeout url = 187 - request ~sw ?client ?headers ?auth ?timeout ~method_:`DELETE url 188 - 189 - let head ~sw ?client ?headers ?auth ?timeout url = 190 - request ~sw ?client ?headers ?auth ?timeout ~method_:`HEAD url 191 - 192 - let patch ~sw ?client ?headers ?body ?auth ?timeout url = 193 - request ~sw ?client ?headers ?body ?auth ?timeout ~method_:`PATCH url 194 - 195 - let upload ~sw ?client ?headers ?auth ?timeout ?method_ ?mime ?length 196 - ?on_progress ~source url = 197 - let method_ = Option.value method_ ~default:`POST in 198 - let mime = Option.value mime ~default:Mime.octet_stream in 199 - 200 - (* Wrap source with progress tracking if callback provided *) 201 - let tracked_source = match on_progress with 202 - | None -> source 203 - | Some callback -> 204 - (* For now, progress tracking is not implemented for uploads 205 - due to complexity of wrapping Eio.Flow.source. 206 - This would require creating a custom flow wrapper. *) 207 - let _ = callback in 208 - source 209 - in 210 - 211 - let body = Body.of_stream ?length mime tracked_source in 212 - request ~sw ?client ?headers ~body ?auth ?timeout ~method_ url 213 - 214 - let download ~sw ?client ?headers ?auth ?timeout ?on_progress url ~sink = 215 - let response = get ~sw ?client ?headers ?auth ?timeout url in 216 - 217 - try 218 - (* Get content length for progress tracking *) 219 - let total = Response.content_length response in 220 - 221 - let body = Response.body response in 222 - 223 - (* Stream data to sink with optional progress *) 224 - match on_progress with 225 - | None -> 226 - (* No progress tracking, just copy directly *) 227 - Eio.Flow.copy body sink 228 - | Some progress_fn -> 229 - (* Copy with progress tracking *) 230 - (* We need to intercept the flow to track bytes *) 231 - (* For now, just do a simple copy - proper progress tracking needs flow wrapper *) 232 - progress_fn ~received:0L ~total; 233 - Eio.Flow.copy body sink; 234 - progress_fn ~received:(Option.value total ~default:0L) ~total; 235 - 236 - Response.close response 237 - with e -> 238 - Response.close response; 239 - raise e
-109
stack/requests/lib/stream.mli
··· 1 - (** Streaming HTTP interface *) 2 - 3 - (** Exceptions - re-exported from Error module for backward compatibility *) 4 - 5 - val request : 6 - sw:Eio.Switch.t -> 7 - ?client:(_ Eio.Time.clock , _ Eio.Net.t) Client.t -> 8 - ?headers:Headers.t -> 9 - ?body:Body.t -> 10 - ?auth:Auth.t -> 11 - ?timeout:Timeout.t -> 12 - ?follow_redirects:bool -> 13 - ?max_redirects:int -> 14 - method_:Method.t -> 15 - string -> 16 - Response.t 17 - (** Make a streaming request *) 18 - 19 - val get : 20 - sw:Eio.Switch.t -> 21 - ?client:(_ Eio.Time.clock , _ Eio.Net.t) Client.t -> 22 - ?headers:Headers.t -> 23 - ?auth:Auth.t -> 24 - ?timeout:Timeout.t -> 25 - ?follow_redirects:bool -> 26 - ?max_redirects:int -> 27 - string -> 28 - Response.t 29 - (** GET request *) 30 - 31 - val post : 32 - sw:Eio.Switch.t -> 33 - ?client:(_ Eio.Time.clock , _ Eio.Net.t) Client.t -> 34 - ?headers:Headers.t -> 35 - ?body:Body.t -> 36 - ?auth:Auth.t -> 37 - ?timeout:Timeout.t -> 38 - string -> 39 - Response.t 40 - (** POST request *) 41 - 42 - val put : 43 - sw:Eio.Switch.t -> 44 - ?client:(_ Eio.Time.clock , _ Eio.Net.t) Client.t -> 45 - ?headers:Headers.t -> 46 - ?body:Body.t -> 47 - ?auth:Auth.t -> 48 - ?timeout:Timeout.t -> 49 - string -> 50 - Response.t 51 - (** PUT request *) 52 - 53 - val delete : 54 - sw:Eio.Switch.t -> 55 - ?client:(_ Eio.Time.clock , _ Eio.Net.t) Client.t -> 56 - ?headers:Headers.t -> 57 - ?auth:Auth.t -> 58 - ?timeout:Timeout.t -> 59 - string -> 60 - Response.t 61 - (** DELETE request *) 62 - 63 - val head : 64 - sw:Eio.Switch.t -> 65 - ?client:(_ Eio.Time.clock , _ Eio.Net.t) Client.t -> 66 - ?headers:Headers.t -> 67 - ?auth:Auth.t -> 68 - ?timeout:Timeout.t -> 69 - string -> 70 - Response.t 71 - (** HEAD request *) 72 - 73 - val patch : 74 - sw:Eio.Switch.t -> 75 - ?client:(_ Eio.Time.clock , _ Eio.Net.t) Client.t -> 76 - ?headers:Headers.t -> 77 - ?body:Body.t -> 78 - ?auth:Auth.t -> 79 - ?timeout:Timeout.t -> 80 - string -> 81 - Response.t 82 - (** PATCH request *) 83 - 84 - val upload : 85 - sw:Eio.Switch.t -> 86 - ?client:(_ Eio.Time.clock , _ Eio.Net.t) Client.t -> 87 - ?headers:Headers.t -> 88 - ?auth:Auth.t -> 89 - ?timeout:Timeout.t -> 90 - ?method_:Method.t -> 91 - ?mime:Mime.t -> 92 - ?length:int64 -> 93 - ?on_progress:(sent:int64 -> total:int64 option -> unit) -> 94 - source:Eio.Flow.source_ty Eio.Resource.t -> 95 - string -> 96 - Response.t 97 - (** Upload from stream *) 98 - 99 - val download : 100 - sw:Eio.Switch.t -> 101 - ?client:(_ Eio.Time.clock , _ Eio.Net.t) Client.t -> 102 - ?headers:Headers.t -> 103 - ?auth:Auth.t -> 104 - ?timeout:Timeout.t -> 105 - ?on_progress:(received:int64 -> total:int64 option -> unit) -> 106 - string -> 107 - sink:Eio.Flow.sink_ty Eio.Resource.t -> 108 - unit 109 - (** Download to stream *)