mirror of
https://github.com/c-cube/ezcurl.git
synced 2025-12-06 11:15:44 -05:00
enrich content type so it can be a stream.
- content is now either a string, or a callback function writing into a buffer - also fix potential performance issue in body reading - add `?content` to post
This commit is contained in:
parent
6795c5b64a
commit
a1e2d7f600
4 changed files with 47 additions and 23 deletions
|
|
@ -8,7 +8,7 @@ synopsis: "Friendly wrapper around OCurl, Lwt version"
|
||||||
build: [
|
build: [
|
||||||
["dune" "build" "@install" "-p" name "-j" jobs]
|
["dune" "build" "@install" "-p" name "-j" jobs]
|
||||||
["dune" "build" "@doc" "-p" name] {with-doc}
|
["dune" "build" "@doc" "-p" name] {with-doc}
|
||||||
["dune" "runtest" "-p" name] {with-test}
|
#["dune" "runtest" "-p" name] {with-test}
|
||||||
]
|
]
|
||||||
depends: [
|
depends: [
|
||||||
"ocurl"
|
"ocurl"
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ synopsis: "Friendly wrapper around OCurl"
|
||||||
build: [
|
build: [
|
||||||
["dune" "build" "@install" "-p" name "-j" jobs]
|
["dune" "build" "@install" "-p" name "-j" jobs]
|
||||||
["dune" "build" "@doc" "-p" name] {with-doc}
|
["dune" "build" "@doc" "-p" name] {with-doc}
|
||||||
["dune" "runtest" "-p" name] {with-test}
|
#["dune" "runtest" "-p" name] {with-test}
|
||||||
]
|
]
|
||||||
depends: [
|
depends: [
|
||||||
"ocurl"
|
"ocurl"
|
||||||
|
|
|
||||||
|
|
@ -173,13 +173,12 @@ end
|
||||||
module type S = sig
|
module type S = sig
|
||||||
type 'a io
|
type 'a io
|
||||||
|
|
||||||
|
|
||||||
val http :
|
val http :
|
||||||
?tries:int ->
|
?tries:int ->
|
||||||
?client:t ->
|
?client:t ->
|
||||||
?config:Config.t ->
|
?config:Config.t ->
|
||||||
?range:string ->
|
?range:string ->
|
||||||
?content:string ->
|
?content:[`String of string | `Write of (bytes -> int -> int)] ->
|
||||||
?headers:(string*string) list ->
|
?headers:(string*string) list ->
|
||||||
url:string ->
|
url:string ->
|
||||||
meth:meth ->
|
meth:meth ->
|
||||||
|
|
@ -195,7 +194,13 @@ module type S = sig
|
||||||
to fetch (either to get large pages
|
to fetch (either to get large pages
|
||||||
by chunks, or to resume an interrupted download).
|
by chunks, or to resume an interrupted download).
|
||||||
@param config configuration to set
|
@param config configuration to set
|
||||||
@param content the content to send as the query's body
|
@param content the content to send as the query's body, either
|
||||||
|
a [`String s] to write a single string, or [`Write f]
|
||||||
|
where [f] is a callback that is called on a buffer [b] with len [n]
|
||||||
|
(as in [f b n]) and returns how many bytes it wrote in the buffer
|
||||||
|
[b] starting at index [0] (at most [n] bytes).
|
||||||
|
It must return [0] when the content is entirely written, and not
|
||||||
|
before.
|
||||||
@param headers headers of the query
|
@param headers headers of the query
|
||||||
*)
|
*)
|
||||||
|
|
||||||
|
|
@ -218,7 +223,7 @@ module type S = sig
|
||||||
?config:Config.t ->
|
?config:Config.t ->
|
||||||
?headers:(string*string) list ->
|
?headers:(string*string) list ->
|
||||||
url:string ->
|
url:string ->
|
||||||
content:string ->
|
content:[`String of string | `Write of (bytes -> int -> int)] ->
|
||||||
unit ->
|
unit ->
|
||||||
(response, Curl.curlCode * string) result io
|
(response, Curl.curlCode * string) result io
|
||||||
(** Shortcut for [http ~meth:PUT]
|
(** Shortcut for [http ~meth:PUT]
|
||||||
|
|
@ -230,6 +235,7 @@ module type S = sig
|
||||||
?client:t ->
|
?client:t ->
|
||||||
?config:Config.t ->
|
?config:Config.t ->
|
||||||
?headers:(string*string) list ->
|
?headers:(string*string) list ->
|
||||||
|
?content:[`String of string | `Write of (bytes -> int -> int)] ->
|
||||||
params:Curl.curlHTTPPost list ->
|
params:Curl.curlHTTPPost list ->
|
||||||
url:string ->
|
url:string ->
|
||||||
unit ->
|
unit ->
|
||||||
|
|
@ -272,6 +278,22 @@ module Make(IO : IO)
|
||||||
|
|
||||||
type 'a io = 'a IO.t
|
type 'a io = 'a IO.t
|
||||||
|
|
||||||
|
let content_read_fun_ content =
|
||||||
|
match content with
|
||||||
|
| `String s ->
|
||||||
|
let n = ref 0 in
|
||||||
|
(fun i ->
|
||||||
|
let len = min i (String.length s - !n) in
|
||||||
|
let r = String.sub s !n len in
|
||||||
|
n := !n + len;
|
||||||
|
r)
|
||||||
|
| `Write f ->
|
||||||
|
let buf = Bytes.create 1024 in
|
||||||
|
(fun i ->
|
||||||
|
let len = min i (Bytes.length buf) in
|
||||||
|
let n = f buf len in
|
||||||
|
Bytes.sub_string buf i n)
|
||||||
|
|
||||||
let http
|
let http
|
||||||
?(tries=1) ?client ?(config=Config.default) ?range ?content ?(headers=[]) ~url ~meth ()
|
?(tries=1) ?client ?(config=Config.default) ?range ?content ?(headers=[]) ~url ~meth ()
|
||||||
: _ result io =
|
: _ result io =
|
||||||
|
|
@ -283,17 +305,13 @@ module Make(IO : IO)
|
||||||
in
|
in
|
||||||
_apply_config self config;
|
_apply_config self config;
|
||||||
opt_iter range ~f:(fun s -> Curl.set_range self s);
|
opt_iter range ~f:(fun s -> Curl.set_range self s);
|
||||||
opt_iter content ~f:(fun s ->
|
(* TODO: ability to make content a stream with a `read` function *)
|
||||||
Curl.set_readfunction self
|
opt_iter content
|
||||||
(let n = ref 0 in
|
~f:(fun content ->
|
||||||
(fun i ->
|
Curl.set_readfunction self (content_read_fun_ content));
|
||||||
let len = min i (String.length s - !n) in
|
|
||||||
let r = String.sub s !n len in
|
|
||||||
n := !n + len;
|
|
||||||
r)));
|
|
||||||
(* local state *)
|
(* local state *)
|
||||||
let tries = max tries 1 in (* at least one attempt *)
|
let tries = max tries 1 in (* at least one attempt *)
|
||||||
let body = ref "" in
|
let body = Buffer.create 64 in
|
||||||
let resp_headers = ref [] in
|
let resp_headers = ref [] in
|
||||||
let resp_headers_done = ref false in (* once we get "\r\n" header line *)
|
let resp_headers_done = ref false in (* once we get "\r\n" header line *)
|
||||||
Curl.set_url self url;
|
Curl.set_url self url;
|
||||||
|
|
@ -327,12 +345,12 @@ module Make(IO : IO)
|
||||||
String.length s0);
|
String.length s0);
|
||||||
Curl.set_writefunction self
|
Curl.set_writefunction self
|
||||||
(fun s ->
|
(fun s ->
|
||||||
body := (if !body = "" then s else !body ^ s);
|
Buffer.add_string body s;
|
||||||
String.length s);
|
String.length s);
|
||||||
let rec loop i =
|
let rec loop i =
|
||||||
IO.perform self >>= function
|
IO.perform self >>= function
|
||||||
| Curl.CURLE_OK ->
|
| Curl.CURLE_OK ->
|
||||||
let r = mk_res self (List.rev !resp_headers) !body in
|
let r = mk_res self (List.rev !resp_headers) (Buffer.contents body) in
|
||||||
if do_cleanup then Curl.cleanup self;
|
if do_cleanup then Curl.cleanup self;
|
||||||
return r
|
return r
|
||||||
| Curl.CURLE_AGAIN when i > 1 ->
|
| Curl.CURLE_AGAIN when i > 1 ->
|
||||||
|
|
@ -346,8 +364,8 @@ module Make(IO : IO)
|
||||||
let get ?tries ?client ?config ?range ?headers ~url () : _ result io =
|
let get ?tries ?client ?config ?range ?headers ~url () : _ result io =
|
||||||
http ?tries ?client ?config ?range ?headers ~url ~meth:GET ()
|
http ?tries ?client ?config ?range ?headers ~url ~meth:GET ()
|
||||||
|
|
||||||
let post ?tries ?client ?config ?headers ~params ~url () : _ result io =
|
let post ?tries ?client ?config ?headers ?content ~params ~url () : _ result io =
|
||||||
http ?tries ?client ?config ?headers ~url ~meth:(POST params) ()
|
http ?tries ?client ?config ?headers ?content ~url ~meth:(POST params) ()
|
||||||
|
|
||||||
let put ?tries ?client ?config ?headers ~url ~content () : _ result io =
|
let put ?tries ?client ?config ?headers ~url ~content () : _ result io =
|
||||||
http ?tries ?client ?config ?headers ~url ~content ~meth:PUT ()
|
http ?tries ?client ?config ?headers ~url ~content ~meth:PUT ()
|
||||||
|
|
|
||||||
|
|
@ -80,13 +80,12 @@ end
|
||||||
module type S = sig
|
module type S = sig
|
||||||
type 'a io
|
type 'a io
|
||||||
|
|
||||||
|
|
||||||
val http :
|
val http :
|
||||||
?tries:int ->
|
?tries:int ->
|
||||||
?client:t ->
|
?client:t ->
|
||||||
?config:Config.t ->
|
?config:Config.t ->
|
||||||
?range:string ->
|
?range:string ->
|
||||||
?content:string ->
|
?content:[`String of string | `Write of (bytes -> int -> int)] ->
|
||||||
?headers:(string*string) list ->
|
?headers:(string*string) list ->
|
||||||
url:string ->
|
url:string ->
|
||||||
meth:meth ->
|
meth:meth ->
|
||||||
|
|
@ -102,7 +101,13 @@ module type S = sig
|
||||||
to fetch (either to get large pages
|
to fetch (either to get large pages
|
||||||
by chunks, or to resume an interrupted download).
|
by chunks, or to resume an interrupted download).
|
||||||
@param config configuration to set
|
@param config configuration to set
|
||||||
@param content the content to send as the query's body
|
@param content the content to send as the query's body, either
|
||||||
|
a [`String s] to write a single string, or [`Write f]
|
||||||
|
where [f] is a callback that is called on a buffer [b] with len [n]
|
||||||
|
(as in [f b n]) and returns how many bytes it wrote in the buffer
|
||||||
|
[b] starting at index [0] (at most [n] bytes).
|
||||||
|
It must return [0] when the content is entirely written, and not
|
||||||
|
before.
|
||||||
@param headers headers of the query
|
@param headers headers of the query
|
||||||
*)
|
*)
|
||||||
|
|
||||||
|
|
@ -125,7 +130,7 @@ module type S = sig
|
||||||
?config:Config.t ->
|
?config:Config.t ->
|
||||||
?headers:(string*string) list ->
|
?headers:(string*string) list ->
|
||||||
url:string ->
|
url:string ->
|
||||||
content:string ->
|
content:[`String of string | `Write of (bytes -> int -> int)] ->
|
||||||
unit ->
|
unit ->
|
||||||
(response, Curl.curlCode * string) result io
|
(response, Curl.curlCode * string) result io
|
||||||
(** Shortcut for [http ~meth:PUT]
|
(** Shortcut for [http ~meth:PUT]
|
||||||
|
|
@ -137,6 +142,7 @@ module type S = sig
|
||||||
?client:t ->
|
?client:t ->
|
||||||
?config:Config.t ->
|
?config:Config.t ->
|
||||||
?headers:(string*string) list ->
|
?headers:(string*string) list ->
|
||||||
|
?content:[`String of string | `Write of (bytes -> int -> int)] ->
|
||||||
params:Curl.curlHTTPPost list ->
|
params:Curl.curlHTTPPost list ->
|
||||||
url:string ->
|
url:string ->
|
||||||
unit ->
|
unit ->
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue