@@ -120,9 +120,9 @@ module type CURL = sig
120120end
121121
122122type ('body,'ret) http_request_ =
123+ ?verbose:bool ->
123124 ?ua:string ->
124125 ?timeout:int ->
125- ?verbose:bool ->
126126 ?setup:(Curl .t -> unit ) ->
127127 ?timer:Action .timer ->
128128 ?max_size:int ->
@@ -141,30 +141,53 @@ module type HTTP = sig
141141 type ('body,'ret) request_ = ('body ,'ret IO .t ) http_request_
142142 type 'ret request = 'ret IO .t http_request
143143
144- val http_request' : [> `Error of Curl .curlCode | `Ok of int * string ] request
145- val http_request : [> `Error of string | `Ok of string ] request
144+ (* * this is the most general form, pass [result] callback to massage the result before returning from the function
145+ e.g. if you need the redirect url in case of 3xx, do [http_request_k ~result:http_result] *)
146+ val http_request_k : result :(Curl .t * (int * string , Curl .curlCode ) result -> 'r ) -> 'r request
147+
148+ (* * this is the most straightforward result of http status code and content or error code *)
149+ val http_request' : [ `Error of Curl .curlCode | `Ok of int * string ] request
150+
151+ (* * even easier - content on HTTP 2xx or error message *)
152+ val http_request : [ `Error of string | `Ok of string ] request
153+
154+ (* * same as {!http_request} but raise exception on non-2xx *)
146155 val http_request_exn : string request
147- val http_query : (string * string , [> `Error of string | `Ok of string ]) request_
156+
157+ (* * send GET with a given content-type and body *)
158+ val http_query : (string * string , [ `Error of string | `Ok of string ]) request_
159+
160+ (* * send POST with key-value form parameters *)
148161 val http_submit :
162+ ?verbose : bool ->
149163 ?ua : string ->
150164 ?timeout : int ->
151- ?verbose : bool ->
152165 ?setup : (Curl .t -> unit ) ->
153166 ?timer : Action .timer ->
154167 ?http_1_0 : bool ->
155168 ?headers : string list ->
156169 ?action : http_action ->
157170 string ->
158- (string * string ) list -> [> `Error of string | `Ok of string ] IO .t
171+ (string * string ) list -> [ `Error of string | `Ok of string ] IO .t
159172end
160173
161174let show_result ?(verbose =false ) = function
162- | `Error code -> sprintf " (%d) %s" (Curl. errno code) (Curl. strerror code)
163- | `Ok (n , content ) -> sprintf " http %d%s" n (if verbose then " : " ^ content else " " )
164-
165- let simple_result ?(is_ok =(fun code -> code / 100 = 2 )) ?verbose = function
166- | `Ok (code , s ) when is_ok code -> `Ok s
167- | r -> `Error (show_result ?verbose r)
175+ | Error code -> sprintf " (%d) %s" (Curl. errno code) (Curl. strerror code)
176+ | Ok (n , content ) -> sprintf " http %d%s" n (if verbose then " : " ^ content else " " )
177+
178+ let simple_result ?verbose (_ ,r ) =
179+ match r with
180+ | Ok (n ,s ) when n / 100 = 2 -> `Ok s
181+ | r -> `Error (show_result ?verbose r)
182+
183+ let http_result ?verbose (h ,r ) =
184+ match r with
185+ | Error _ -> `Error (show_result ?verbose r)
186+ | Ok (n ,(s :string )) ->
187+ match n/ 100 with
188+ | 2 -> `Ok (n,s)
189+ | 3 -> `Redirect (n, Curl. get_redirecturl h)
190+ | _ -> `Http (n,s)
168191
169192let nr_http = ref 0
170193
@@ -190,6 +213,7 @@ module Http (IO : IO_TYPE) (Curl_IO : CURL with type 'a t = 'a IO.t) : HTTP with
190213 " server.address" , `String (Curl. get_primaryip h);
191214 (* NOTE: this crashes with
192215 exn File "curl.ml", line 1365, characters 9-15: Assertion failed
216+ before ocurl 0.11.0
193217 "network.protocol.version", `String (match Curl.get_http_version h with
194218 | HTTP_VERSION_1_0 -> "1.0" | HTTP_VERSION_1_1 -> "1.1"
195219 | HTTP_VERSION_2 | HTTP_VERSION_2TLS | HTTP_VERSION_2_PRIOR_KNOWLEDGE -> "2"
@@ -210,33 +234,27 @@ module Http (IO : IO_TYPE) (Curl_IO : CURL with type 'a t = 'a IO.t) : HTTP with
210234 ()
211235
212236 (* deprecated *)
213- let http_gets ?( setup =ignore) ?timer ?max_size ?( check =( fun _ -> true )) ?( result =( fun _ _ -> return_unit)) url =
237+ let http_gets ~ setup ?timer ?max_size ~ result url =
214238 with_curl_cache begin fun h ->
215239 Curl. set_url h url;
216240 curl_default_setup h;
217- let () = setup h in
241+ setup h;
218242 let b = Buffer. create 10 in
219243 let read_size = ref 0 in
220244 Curl. set_writefunction h begin fun s ->
221- match check h with
222- | false -> 0
223- | true ->
224- Buffer. add_string b s;
225- let l = String. length s in
226- read_size += l;
227- match max_size with
228- | Some max_size when ! read_size > max_size -> Exn. fail " received too much data (%db) when max is %db" ! read_size max_size
229- | _ -> l
245+ Buffer. add_string b s;
246+ let l = String. length s in
247+ read_size += l;
248+ match max_size with
249+ | Some max_size when ! read_size > max_size -> Exn. fail " received too much data (%db) when max is %db" ! read_size max_size
250+ | _ -> l
230251 end;
231252 timer |> Option. may (fun t -> t#mark " Web.http" );
232253 catch (fun () -> Curl_IO. perform h) (fun exn -> update_timer h timer; IO. raise exn ) >> = fun code ->
233- (update_timer h timer; result h code) >> = fun () ->
234- return @@ match code with
235- | Curl. CURLE_OK -> `Ok (Curl. get_httpcode h, Buffer. contents b)
236- | code -> `Error code
254+ (update_timer h timer; return @@ result (h,match code with CURLE_OK -> Ok (Curl. get_httpcode h, Buffer. contents b) | err -> Error err))
237255 end
238256
239- let verbose_curl_result_plain nr_http action t h code =
257+ let verbose_curl_result_plain nr_http action t ( h , r ) =
240258 let open Curl in
241259 let b = Buffer. create 10 in
242260 bprintf b " %s #%d %s ⇓%s ⇑%s %s "
@@ -245,9 +263,9 @@ module Http (IO : IO_TYPE) (Curl_IO : CURL with type 'a t = 'a IO.t) : HTTP with
245263 (Action. bytes_string_f @@ get_sizeupload h)
246264 (get_primaryip h)
247265 ;
248- begin match code with
249- | CURLE_OK ->
250- bprintf b " HTTP %d %s" (get_httpcode h) (get_effectiveurl h);
266+ begin match r with
267+ | Ok ( code , _ ) ->
268+ bprintf b " HTTP %d %s" code (get_effectiveurl h);
251269 begin match get_redirecturl h with
252270 | "" -> ()
253271 | s -> bprintf b " -> %s" s
@@ -256,12 +274,12 @@ module Http (IO : IO_TYPE) (Curl_IO : CURL with type 'a t = 'a IO.t) : HTTP with
256274 | 0 -> ()
257275 | n -> bprintf b " after %d redirects" n
258276 end
259- | _ ->
277+ | Error code ->
260278 bprintf b " error (%d) %s (errno %d)" (errno code) (strerror code) (Curl. get_oserrno h)
261279 end ;
262280 log #info_s (Buffer. contents b)
263281
264- let verbose_curl_result_logfmt nr_http action t h code =
282+ let verbose_curl_result_logfmt nr_http action t ( h , r ) =
265283 let open Curl in
266284 let size_down = get_sizedownload h in
267285 let size_up = get_sizeupload h in
@@ -279,13 +297,13 @@ module Http (IO : IO_TYPE) (Curl_IO : CURL with type 'a t = 'a IO.t) : HTTP with
279297 | 0 -> base
280298 | n -> (" http_status" , string_of_int n) :: base
281299 in
282- match code with
283- | CURLE_OK ->
300+ match r with
301+ | Ok _ ->
284302 let pairs = (" url" , get_effectiveurl h) :: base in
285303 let pairs = match get_redirecturl h with "" -> pairs | s -> (" redirect" , s) :: pairs in
286304 let pairs = match get_redirectcount h with 0 -> pairs | n -> (" redirect_count" , string_of_int n) :: pairs in
287305 log #info ~pairs " http done"
288- | _ ->
306+ | Error code ->
289307 let pairs =
290308 (" err" , strerror code) ::
291309 (" errno" , string_of_int (errno code)) ::
@@ -294,10 +312,10 @@ module Http (IO : IO_TYPE) (Curl_IO : CURL with type 'a t = 'a IO.t) : HTTP with
294312 in
295313 log #info ~pairs " http error"
296314
297- let verbose_curl_result nr_http action t h code =
315+ let verbose_curl_result nr_http action t hr =
298316 match Log.State. get_cur_format () with
299- | `Plain , _ -> verbose_curl_result_plain nr_http action t h code
300- | `Logfmt , _ -> verbose_curl_result_logfmt nr_http action t h code
317+ | `Plain , _ -> verbose_curl_result_plain nr_http action t hr
318+ | `Logfmt , _ -> verbose_curl_result_logfmt nr_http action t hr
301319
302320 (* Given a list of strings, check pre-existing entry starting with `~name`; and adds the concatenation of `~name` and `~value` if not. *)
303321 let add_if_absent ~name ~value strs =
@@ -308,7 +326,7 @@ module Http (IO : IO_TYPE) (Curl_IO : CURL with type 'a t = 'a IO.t) : HTTP with
308326
309327 (* NOTE don't forget to set http_1_0=true when sending requests to a Httpev-based server *)
310328 (* Don't use curl_setheaders when using ?headers option *)
311- let http_request' ? ua ? timeout ? (verbose =false ) ?(setup =ignore) ?timer ?max_size ?(http_1_0 =false ) ?headers ?body (action :http_action ) url =
329+ let http_request_k ~ result ? (verbose =false ) ? ua ? timeout ?(setup =ignore) ?timer ?max_size ?(http_1_0 =false ) ?headers ?body (action :http_action ) url =
312330 let open Curl in
313331 let action_name = string_of_http_action action in
314332 let ch_query_id = ref None in
@@ -382,7 +400,7 @@ module Http (IO : IO_TYPE) (Curl_IO : CURL with type 'a t = 'a IO.t) : HTTP with
382400 let span_name = Printf. sprintf " devkit.web.%s" action_name in
383401 (* We set the value of `__FUNCTION__` to preserve the build with OCaml < 4.12. *)
384402 Possibly_otel. enter_manual_span
385- ~__FUNCTION__:" Devkit.Web.Http.http_request' " ~__FILE__ ~__LINE__ ~data: describe span_name in
403+ ~__FUNCTION__:" Devkit.Web.Http.http_request_k " ~__FILE__ ~__LINE__ ~data: describe span_name in
386404
387405 let headers = match Possibly_otel.Traceparent. get_ambient ~explicit_span () with
388406 | None -> headers
@@ -396,38 +414,37 @@ module Http (IO : IO_TYPE) (Curl_IO : CURL with type 'a t = 'a IO.t) : HTTP with
396414 in
397415
398416 let t = new Action. timer in
399- let result = Some (fun h code ->
400- if verbose then verbose_curl_result nr_http action t h code;
401- if Trace_core. enabled () then (
417+ let result (h ,_ as res ) =
418+ if verbose then verbose_curl_result nr_http action t res;
419+ if Trace_core. enabled () then
420+ begin
402421 let data = get_curl_data h in
403- let data = match ! ch_query_id with None -> data
404- | Some v -> (" http.response.header.x-clickhouse-query-id" , `String v) :: data in
405- let data = match ! ch_summary with None -> data
406- | Some v -> (" http.response.header.x-clickhouse-summary" , `String v) :: data in
407- let data = match ! resp_content_encoding with None -> data
408- | Some v -> (" http.response.header.content-encoding" , `String v) :: data in
422+ let data = match ! ch_query_id with None -> data | Some v -> (" http.response.header.x-clickhouse-query-id" , `String v) :: data in
423+ let data = match ! ch_summary with None -> data | Some v -> (" http.response.header.x-clickhouse-summary" , `String v) :: data in
424+ let data = match ! resp_content_encoding with None -> data | Some v -> (" http.response.header.content-encoding" , `String v) :: data in
409425 Trace_core. add_data_to_span explicit_span data
410- ) ;
426+ end ;
411427 Trace_core. exit_span explicit_span;
412- return ()
413- ) in
428+ result res
429+ in
430+
431+ http_gets ~setup: (setup ~headers set_body_and_headers) ?timer ?max_size ~result url
414432
415- http_gets ~setup: (setup ~headers set_body_and_headers) ?timer ?result ?max_size url
433+ (* could be [~result:snd], but need to keep compatibility *)
434+ let http_request' = http_request_k ~result: (function (_ ,Ok x ) -> `Ok x | (_ ,Error e ) -> `Error e)
416435
417- let http_request ?ua ?timeout ?verbose ?setup ?timer ?max_size ?http_1_0 ?headers ?body (action :http_action ) url =
418- http_request' ?ua ?timeout ?verbose ?setup ?timer ?max_size ?http_1_0 ?headers ?body action url >> = fun res ->
419- return @@ simple_result ?verbose res
436+ let http_request ?verbose = http_request_k ?verbose ~result: (simple_result ?verbose)
420437
421- let http_request_exn ?ua ? timeout ? verbose ?setup ?timer ?max_size ?http_1_0 ?headers ?body (action :http_action ) url =
422- http_request ?ua ?timeout ?verbose ?setup ?timer ?max_size ?http_1_0 ?headers ?body action url
438+ let http_request_exn ?verbose ? ua ? timeout ?setup ?timer ?max_size ?http_1_0 ?headers ?body (action :http_action ) url =
439+ http_request ?verbose ?ua ?timeout ?setup ?timer ?max_size ?http_1_0 ?headers ?body action url
423440 >> = function `Ok s -> return s | `Error error -> fail " %s" error
424441
425- let http_query ?ua ? timeout ? verbose ?setup ?timer ?max_size ?http_1_0 ?headers ?body (action :http_action ) url =
442+ let http_query ?verbose ? ua ? timeout ?setup ?timer ?max_size ?http_1_0 ?headers ?body (action :http_action ) url =
426443 let body = match body with Some (ct ,s ) -> Some (`Raw (ct,s)) | None -> None in
427- http_request ?ua ?timeout ?verbose ?setup ?timer ?max_size ?http_1_0 ?headers ?body action url
444+ http_request ?verbose ?ua ?timeout ?setup ?timer ?max_size ?http_1_0 ?headers ?body action url
428445
429- let http_submit ?ua ? timeout ? verbose ?setup ?timer ?http_1_0 ?headers ?(action =`POST ) url args =
430- http_request ?ua ?timeout ?verbose ?setup ?timer ?http_1_0 ?headers ~body: (`Form args) action url
446+ let http_submit ?verbose ? ua ? timeout ?setup ?timer ?http_1_0 ?headers ?(action =`POST ) url args =
447+ http_request ?verbose ?ua ?timeout ?setup ?timer ?http_1_0 ?headers ~body: (`Form args) action url
431448
432449end
433450
471488module Http_blocking = Http (IO_blocking )(Curl_blocking )
472489module Http_lwt = Http (IO_lwt )(Curl_lwt_for_http )
473490
491+ (* there is also Http_blocking.http_request_k *)
474492let with_curl = Http_blocking. with_curl
475493let with_curl_cache = Http_blocking. with_curl_cache
476494let http_request' = Http_blocking. http_request'
@@ -479,6 +497,7 @@ let http_request_exn = Http_blocking.http_request_exn
479497let http_query = Http_blocking. http_query
480498let http_submit = Http_blocking. http_submit
481499
500+ (* there is also Http_lwt.http_request_k *)
482501let http_request_lwt' = Http_lwt. http_request'
483502let http_request_lwt = Http_lwt. http_request
484503let http_request_lwt_exn = Http_lwt. http_request_exn
0 commit comments