Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ Planned changes for 1.0:

* Make the Lwt response stream bounded (new in lwt-2.4+)

* Should read_form really be in lib/ ? It could just be implemented in the
drivers. But then again, that would be repeated code in all the backends.

Planned changes for 2.0:

* Make the Header.t header parsing more efficient by only lazily parsing them
Expand Down
14 changes: 0 additions & 14 deletions _oasis
Original file line number Diff line number Diff line change
Expand Up @@ -183,15 +183,6 @@ Executable test_parser
Install: false
BuildDepends: cohttp, cohttp.lwt, oUnit (>= 1.0.2)

Executable test_parser_async
Path: lib_test
MainIs: test_parser_async.ml
Build$: flag(tests) && flag(async)
Custom: true
CompiledObject: best
Install: false
BuildDepends: cohttp, cohttp.async, oUnit (>= 1.0.2)

Executable test_accept
Path: lib_test
MainIs: test_accept.ml
Expand Down Expand Up @@ -455,11 +446,6 @@ Test test_parser
Command: $test_parser
WorkingDirectory: lib_test

Test test_parser_async
Run$: flag(tests) && flag(async)
Command: $test_parser_async
WorkingDirectory: lib_test

Test test_sanity
Run$: flag(tests) && flag(lwt_unix)
Command: $test_sanity
Expand Down
21 changes: 1 addition & 20 deletions _tags
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# OASIS_START
# DO NOT EDIT (digest: 96c43695999b12657423ef4f010e1492)
# DO NOT EDIT (digest: 157821268a2c635ce673f84a8e5077b5)
# Ignore VCS directories, you can use the same kind of rule outside
# OASIS_START/STOP if you want to exclude directories that contains
# useless stuff for the build process
Expand Down Expand Up @@ -151,25 +151,6 @@ true: annot, bin_annot
<lib_test/test_parser.{native,byte}>: use_cohttp_lwt
<lib_test/test_parser.{native,byte}>: use_cohttp_lwt_unix
<lib_test/test_parser.{native,byte}>: custom
# Executable test_parser_async
<lib_test/test_parser_async.{native,byte}>: pkg_async
<lib_test/test_parser_async.{native,byte}>: pkg_base64
<lib_test/test_parser_async.{native,byte}>: pkg_bytes
<lib_test/test_parser_async.{native,byte}>: pkg_conduit.async
<lib_test/test_parser_async.{native,byte}>: pkg_fieldslib
<lib_test/test_parser_async.{native,byte}>: pkg_fieldslib.syntax
<lib_test/test_parser_async.{native,byte}>: pkg_magic-mime
<lib_test/test_parser_async.{native,byte}>: pkg_oUnit
<lib_test/test_parser_async.{native,byte}>: pkg_re.emacs
<lib_test/test_parser_async.{native,byte}>: pkg_sexplib
<lib_test/test_parser_async.{native,byte}>: pkg_sexplib.syntax
<lib_test/test_parser_async.{native,byte}>: pkg_stringext
<lib_test/test_parser_async.{native,byte}>: pkg_threads
<lib_test/test_parser_async.{native,byte}>: pkg_uri
<lib_test/test_parser_async.{native,byte}>: pkg_uri.services
<lib_test/test_parser_async.{native,byte}>: use_cohttp
<lib_test/test_parser_async.{native,byte}>: use_cohttp_async
<lib_test/test_parser_async.{native,byte}>: custom
# Executable test_accept
<lib_test/test_accept.{native,byte}>: pkg_base64
<lib_test/test_accept.{native,byte}>: pkg_bytes
Expand Down
6 changes: 3 additions & 3 deletions async/cohttp_async.ml
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,8 @@ module Client = struct
responses

let call ?interrupt ?headers ?(chunked=false) ?(body=`Empty) meth uri =
(* Create a request, then make the request.
Figure out an appropriate transfer encoding *)
(* Create a request, then make the request. Figure out an appropriate
transfer encoding *)
let req =
match chunked with
| false ->
Expand All @@ -221,7 +221,7 @@ module Client = struct
Request.make_for_client ?headers ~chunked ~body_length meth uri
| true -> begin
Body.is_empty body >>| function
| true -> (* Dont used chunked encoding with an empty body *)
| true -> (* Don't used chunked encoding with an empty body *)
Request.make_for_client ?headers ~chunked:false ~body_length:0L meth uri
| false -> (* Use chunked encoding if there is a body *)
Request.make_for_client ?headers ~chunked:true meth uri
Expand Down
17 changes: 2 additions & 15 deletions async/cohttp_async.mli
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,8 @@
open Core.Std
open Async.Std

(** Read in a full body and convert to a [string] *)

module IO : (module type of Cohttp_async_io)

module Request : sig
type t = Cohttp.Request.t
include Cohttp.S.Request with type t := Cohttp.Request.t
include Cohttp.S.Http_io with type t := Cohttp.Request.t and module IO=IO
end

module Response : sig
type t = Cohttp.Response.t
include Cohttp.S.Response with type t := Cohttp.Response.t
include Cohttp.S.Http_io with type t := Cohttp.Response.t and module IO=IO
end
module Request : Cohttp.S.Request with type t = Cohttp.Request.t
module Response : Cohttp.S.Response with type t = Cohttp.Response.t

module Body : sig
type t = [
Expand Down
12 changes: 6 additions & 6 deletions js/cohttp_lwt_xhr.ml
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ end

module Make_api(X : sig

module Request : Cohttp_lwt.S.Request
module Response : Cohttp_lwt.S.Response
module Request : Cohttp.S.Request
module Response : Cohttp.S.Response

val call :
?headers:Cohttp.Header.t ->
Expand Down Expand Up @@ -102,8 +102,8 @@ end
module Make_client_async(P : Params) = Make_api(struct

module IO = String_io_lwt
module Response = Cohttp_lwt.Make_response(IO)
module Request = Cohttp_lwt.Make_request(IO)
module Response = Cohttp.Response
module Request = Cohttp.Request
module Header_io = Cohttp.Header_io.Make(IO)
module Bb = Body_builder(P)

Expand Down Expand Up @@ -173,8 +173,8 @@ end)
module Make_client_sync(P : Params) = Make_api(struct

module IO = String_io_lwt
module Response = Cohttp_lwt.Make_response(IO)
module Request = Cohttp_lwt.Make_request(IO)
module Response = Cohttp.Response
module Request = Cohttp.Request
module Header_io = Cohttp.Header_io.Make(IO)
module Bb = Body_builder(P)

Expand Down
7 changes: 0 additions & 7 deletions lib/header_io.ml
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,6 @@ module Make(IO : S.IO) = struct
end
in parse_headers' (Header.init ())

let parse_form headers ic =
(* If the form is query-encoded, then extract those parameters also *)
let encoding = Header.get_transfer_encoding headers in
let reader = Transfer_IO.make_reader encoding ic in
Transfer_IO.to_string reader >>= fun body ->
return (Uri.query_of_encoded body)

let write headers oc =
IO.write oc (Header.to_string headers)
end
1 change: 0 additions & 1 deletion lib/header_io.mli
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,5 @@

module Make(IO : S.IO) : sig
val parse: IO.ic -> Header.t IO.t
val parse_form : Header.t -> IO.ic -> (string * string list) list IO.t
val write : Header.t -> IO.oc -> unit IO.t
end
3 changes: 0 additions & 3 deletions lib/request.ml
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,4 @@ module Make(IO : S.IO) = struct
let writer = make_body_writer ?flush req oc in
write_body writer >>= fun () ->
write_footer req oc

let is_form req = Header.is_form req.headers
let read_form req ic = Header_IO.parse_form req.headers ic
end
3 changes: 0 additions & 3 deletions lib/response.ml
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,4 @@ module Make(IO : S.IO) = struct
let writer = make_body_writer ?flush req oc in
fn writer >>= fun () ->
write_footer req oc

let is_form req = Header.is_form req.headers
let read_form req ic = Header_IO.parse_form req.headers ic
end
3 changes: 0 additions & 3 deletions lib/s.mli
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,6 @@ module type Http_io = sig
val make_body_reader : t -> IO.ic -> reader
val read_body_chunk : reader -> Transfer.chunk IO.t

val is_form: t -> bool
val read_form : t -> IO.ic -> (string * string list) list IO.t

val write_header : t -> IO.oc -> unit IO.t
val make_body_writer : ?flush:bool -> t -> IO.oc -> writer
val write_body : writer -> string -> unit IO.t
Expand Down
14 changes: 0 additions & 14 deletions lib/transfer_io.ml
Original file line number Diff line number Diff line change
Expand Up @@ -145,18 +145,4 @@ module Make(IO : S.IO) = struct

let read reader = reader ()
let write writer buf = writer buf

let to_string reader =
let buf = Buffer.create 256 in
let rec loop () =
read reader >>= function
| Chunk c ->
Buffer.add_string buf c;
loop ()
| Final_chunk c ->
Buffer.add_string buf c;
return (Buffer.contents buf)
| Done -> return (Buffer.contents buf)
in
loop ()
end
1 change: 0 additions & 1 deletion lib/transfer_io.mli
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,4 @@ module Make(IO : S.IO) : sig

val read : reader -> chunk IO.t
val write : writer -> string -> unit IO.t
val to_string : reader -> string IO.t
end
67 changes: 27 additions & 40 deletions lib_test/test_parser.ml
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,13 @@ let pp_diff fmt (a,b) =

let p_sexp f x = x |> f |> Sexplib.Sexp.to_string

module Req_io = Cohttp.Request.Make(Cohttp_lwt_unix_io)
module Rep_io = Cohttp.Response.Make(Cohttp_lwt_unix_io)

let basic_req_parse () =
let module CU = Cohttp_lwt_unix in
let ic = ic_of_buffer (Lwt_bytes.of_string basic_req) in
CU.Request.read ic >>=
Req_io.read ic >>=
function
| `Ok req ->
assert_equal (Cohttp.Request.version req) `HTTP_1_1;
Expand All @@ -128,7 +131,7 @@ let basic_res_parse res () =
let open Cohttp in
let open Cohttp_lwt_unix in
let ic = ic_of_buffer (Lwt_bytes.of_string res) in
Response.read ic >>=
Rep_io.read ic >>=
function
| `Ok res ->
(* Parse first line *)
Expand All @@ -145,41 +148,26 @@ let basic_res_parse res () =
let req_parse () =
let open Cohttp_lwt_unix in
let ic = ic_of_buffer (Lwt_bytes.of_string basic_req) in
Request.read ic >>= function
Req_io.read ic >>= function
| `Ok req ->
assert_equal `GET (Request.meth req);
assert_equal "/index.html" ((Uri.path (Request.uri req)));
assert_equal `HTTP_1_1 (Request.version req);
return ()
| _ -> assert false

let post_form_parse () =
let open Cohttp_lwt_unix in
let ic = ic_of_buffer (Lwt_bytes.of_string post_req) in
Request.read ic >>= function
| `Ok req ->
assert_equal true (Request.is_form req);
Request.read_form req ic >>= fun params ->
assert_equal ["Cosby"] (List.assoc "home" params);
assert_equal ["flies"] (List.assoc "favorite flavor" params);
assert_raises Not_found (fun () -> List.assoc "nonexistent" params);
(* multiple requests should still work *)
assert_equal ["Cosby"] (List.assoc "home" params);
return ()
| _ -> assert false

let post_data_parse () =
let open Cohttp in
let open Cohttp_lwt_unix in
let ic = ic_of_buffer (Lwt_bytes.of_string post_data_req) in
Request.read ic >>= function
Req_io.read ic >>= function
| `Ok req ->
let printer = p_sexp Transfer.sexp_of_chunk in
let reader = Request.make_body_reader req ic in
Request.read_body_chunk reader >>= fun body ->
let reader = Req_io.make_body_reader req ic in
Req_io.read_body_chunk reader >>= fun body ->
assert_equal ~printer (Transfer.Final_chunk "home=Cosby&favorite+flavor=flies") body;
(* A subsequent request for the body will have consumed it, therefore None *)
Request.read_body_chunk reader >>= fun body ->
Req_io.read_body_chunk reader >>= fun body ->
assert_equal ~printer Transfer.Done body;
return ()
| _ -> assert false
Expand All @@ -188,13 +176,13 @@ let post_chunked_parse () =
let open Cohttp in
let open Cohttp_lwt_unix in
let ic = ic_of_buffer (Lwt_bytes.of_string post_chunked_req) in
Request.read ic >>= function
Req_io.read ic >>= function
| `Ok req ->
assert_equal (Transfer.string_of_encoding (Request.encoding req)) "chunked";
let reader = Request.make_body_reader req ic in
Request.read_body_chunk reader >>= fun chunk ->
let reader = Req_io.make_body_reader req ic in
Req_io.read_body_chunk reader >>= fun chunk ->
assert_equal chunk (Transfer.Chunk "abcdefghijklmnopqrstuvwxyz");
Request.read_body_chunk reader >>= fun chunk ->
Req_io.read_body_chunk reader >>= fun chunk ->
assert_equal chunk (Transfer.Chunk "1234567890abcdef");
return ()
| _ -> assert false
Expand All @@ -203,12 +191,12 @@ let res_content_parse () =
let open Cohttp in
let open Cohttp_lwt_unix in
let ic = ic_of_buffer (Lwt_bytes.of_string basic_res_content) in
Response.read ic >>= function
Rep_io.read ic >>= function
| `Ok res ->
assert_equal `HTTP_1_1 (Response.version res);
assert_equal `OK (Response.status res);
let reader = Response.make_body_reader res ic in
Response.read_body_chunk reader >>= fun body ->
let reader = Rep_io.make_body_reader res ic in
Rep_io.read_body_chunk reader >>= fun body ->
assert_equal (Transfer.Final_chunk "home=Cosby&favorite+flavor=flies") body;
return ()
| _ -> assert false
Expand All @@ -217,14 +205,14 @@ let res_chunked_parse () =
let open Cohttp in
let open Cohttp_lwt_unix in
let ic = ic_of_buffer (Lwt_bytes.of_string chunked_res) in
Response.read ic >>= function
Rep_io.read ic >>= function
| `Ok res ->
assert_equal `HTTP_1_1 (Response.version res);
assert_equal `OK (Response.status res);
let reader = Response.make_body_reader res ic in
Response.read_body_chunk reader >>= fun chunk ->
let reader = Rep_io.make_body_reader res ic in
Rep_io.read_body_chunk reader >>= fun chunk ->
assert_equal chunk (Transfer.Chunk "abcdefghijklmnopqrstuvwxyz");
Response.read_body_chunk reader >>= fun chunk ->
Rep_io.read_body_chunk reader >>= fun chunk ->
assert_equal chunk (Transfer.Chunk "1234567890abcdef");
return ()
| _ -> assert false
Expand All @@ -243,15 +231,15 @@ let write_req expected req =
let buf = Lwt_bytes.create 4096 in
let oc = oc_of_buffer buf in
let body = Cohttp_lwt_body.of_string "foobar" in
Request.write (fun writer ->
Cohttp_lwt_body.write_body (Request.write_body writer) body
Req_io.write (fun writer ->
Cohttp_lwt_body.write_body (Req_io.write_body writer) body
) req oc >>= fun () ->
assert_equal ~pp_diff expected (get_substring oc buf);
(* Use the high-level write API. This also tests that req is immutable
* by re-using it *)
let buf = Lwt_bytes.create 4096 in
let oc = oc_of_buffer buf in
Request.write (fun writer -> Request.write_body writer "foobar") req oc
Req_io.write (fun writer -> Req_io.write_body writer "foobar") req oc
>|= fun () ->
assert_equal expected (get_substring oc buf)

Expand Down Expand Up @@ -279,23 +267,22 @@ let make_simple_res () =
let oc = oc_of_buffer buf in
let res = Response.make ~headers:(Header.of_list [("foo","bar")]) () in
let body = Cohttp_lwt_body.of_string "foobar" in
Response.write (fun writer ->
Cohttp_lwt_body.write_body (Response.write_body writer) body
Rep_io.write (fun writer ->
Cohttp_lwt_body.write_body (Rep_io.write_body writer) body
) res oc >>= fun () ->
assert_equal expected (get_substring oc buf);
(* Use the high-level write API. This also tests that req is immutable
* by re-using it *)
let buf = Lwt_bytes.create 4096 in
let oc = oc_of_buffer buf in
Response.write (fun writer -> Response.write_body writer "foobar") res oc >>= fun () ->
Rep_io.write (fun writer -> Rep_io.write_body writer "foobar") res oc >>= fun () ->
assert_equal expected (get_substring oc buf);
return ()

let test_cases =
let tests = [
"basic_req_parse", basic_req_parse;
"req_parse", req_parse;
"post_form_parse", post_form_parse;
"post_data_parse", post_data_parse;
"post_chunked_parse", post_chunked_parse;
"basic_res_parse 1", (basic_res_parse basic_res);
Expand Down
Loading