Skip to content

Commit

Permalink
Merge pull request #984 from mefyl/eio
Browse files Browse the repository at this point in the history
Eio backend using stock parsing, serialization and signatures from Cohttp.
  • Loading branch information
mseri authored Oct 15, 2023
2 parents daf1323 + b8a964f commit 6d1c85a
Show file tree
Hide file tree
Showing 37 changed files with 870 additions and 1,728 deletions.
1 change: 1 addition & 0 deletions .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ jobs:
local-packages:
- |
http.opam
cohttp.opam
cohttp-eio.opam
runs-on: ${{ matrix.os }}
Expand Down
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## Unreleased
- cohttp-eio: Complete rewrite to follow common interfaces and behaviors. (mefyl #984)

## v6.0.0~alpha2 (2023-08-08)
- cohttp-lwt: Do not leak exceptions to `Lwt.async_exception_hook`. (mefyl #992, #995)
- http.header, cohttp, cohttp-eio: remove "first" and "move_to_first" and the special treatment of the "host" header (mseri #988, #986)
Expand Down
5 changes: 4 additions & 1 deletion cohttp-eio.opam
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,17 @@ doc: "https://mirage.github.io/ocaml-cohttp/"
bug-reports: "https://github.com/mirage/ocaml-cohttp/issues"
depends: [
"dune" {>= "3.0"}
"alcotest" {with-test}
"base-domains"
"eio" {>= "0.10" & < "0.12"}
"cohttp" {= version}
"eio" {>= "0.12"}
"eio_main" {with-test}
"mdx" {with-test}
"uri" {with-test}
"fmt"
"ptime"
"http" {= version}
"ppx_here" {with-test}
"odoc" {with-doc}
]
dev-repo: "git+https://github.com/mirage/ocaml-cohttp.git"
Expand Down
16 changes: 14 additions & 2 deletions cohttp-eio/examples/client1.ml
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
open Cohttp_eio

let () = Logs.set_reporter (Logs_fmt.reporter ())

and () =
(* The eio backend does not leverage domains yet, but might in the near future *)
Logs_threaded.enable ()

and () = Logs.Src.set_level Cohttp_eio.src (Some Debug)

let () =
Eio_main.run @@ fun env ->
let res = Client.get env ~host:"www.example.org" "/" in
print_string @@ Client.read_fixed res
let client = Client.make env#net in
Eio.Switch.run @@ fun sw ->
let resp, body = Client.get ~sw client (Uri.of_string "http://example.com") in
if Http.Status.compare resp.status `OK = 0 then
print_string @@ Eio.Buf_read.(parse_exn take_all) body ~max_size:max_int
else Fmt.epr "Unexpected HTTP status: %a" Http.Status.pp resp.status
17 changes: 8 additions & 9 deletions cohttp-eio/examples/client_timeout.ml
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
open Eio
open Cohttp_eio

let () =
Eio_main.run @@ fun env ->
Switch.run @@ fun sw ->
let client = Client.make env#net in
(* Increment/decrement this value to see success/failure. *)
let timeout_s = 0.01 in
Eio.Time.with_timeout env#clock timeout_s (fun () ->
let host, port = ("www.example.org", 80) in
let he = Unix.gethostbyname host in
let addr = `Tcp (Eio_unix.Net.Ipaddr.of_unix he.h_addr_list.(0), port) in
let conn = Net.connect ~sw env#net addr in
let res = Client.get ~conn ~port env ~host "/" in
Client.read_fixed res |> Result.ok)
Eio.Switch.run @@ fun sw ->
let _, body =
Client.get client ~sw (Uri.of_string "http://www.example.org")
in
Eio.Buf_read.(of_flow ~max_size:max_int body |> take_all) |> Result.ok)
|> function
| Ok s -> print_string s
| Error `Timeout -> print_string "Connection timed out"
| Error (`Fatal e) -> Fmt.epr "fatal error: %s@." e
| Error `Timeout -> Fmt.epr "Connection timed out@."
20 changes: 13 additions & 7 deletions cohttp-eio/examples/docker_client.ml
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,22 @@ module Client = Cohttp_eio.Client
module Response = Http.Response
module Status = Http.Status

let () = Logs.set_reporter (Logs_fmt.reporter ())
and () = Logs.Src.set_level Cohttp_eio.src (Some Debug)

let () =
Eio_main.run @@ fun env ->
Switch.run @@ fun sw ->
let addr = `Unix "/var/run/docker.sock" in
let conn = Net.connect ~sw env#net addr in
let res = Client.get ~conn ~host:"docker" env "/version" in
let code = fst res |> Response.status |> Status.to_int in
let client = Client.make env#net in
Eio.Switch.run @@ fun sw ->
let response, body =
Client.get client ~sw
@@ Uri.make ~scheme:"httpunix" ~host:"/var/run/docker.sock" ~path:"/version"
()
in
let code = response |> Response.status |> Status.to_int in
Printf.printf "Response code: %d\n" code;
Printf.printf "Headers: %s\n"
(fst res |> Response.headers |> Http.Header.to_string);
let body = Client.read_fixed res in
(response |> Response.headers |> Http.Header.to_string);
let body = Eio.Buf_read.(of_flow ~max_size:max_int body |> take_all) in
Printf.printf "Body of length: %d\n" (String.length body);
print_endline ("Received body\n" ^ body)
2 changes: 1 addition & 1 deletion cohttp-eio/examples/dune
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(executables
(names server1 client1 docker_client client_timeout)
(libraries cohttp-eio eio_main eio.unix unix))
(libraries cohttp-eio eio_main eio.unix fmt unix logs.fmt logs.threaded))

(alias
(name runtest)
Expand Down
28 changes: 19 additions & 9 deletions cohttp-eio/examples/server1.ml
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,29 @@ let text =
was coming to, but it was too dark to see anything; then she looked at the \
sides of the well, and noticed that they were filled with cupboards......"

open Cohttp_eio
let () = Logs.set_reporter (Logs_fmt.reporter ())
and () = Logs.Src.set_level Cohttp_eio.src (Some Debug)

let app : Server.request -> Server.response =
fun ((req, _, _) : Server.request) ->
match Http.Request.resource req with
| "/" -> Server.text_response text
| "/html" -> Server.html_response text
| _ -> Server.not_found_response
let handler _socket request _body =
match Http.Request.resource request with
| "/" -> (Http.Response.make (), Cohttp_eio.Body.of_string text)
| "/html" ->
( Http.Response.make
~headers:(Http.Header.of_list [ ("content-type", "text/html") ])
(),
(* Use a plain flow to test chunked encoding *)
Eio.Flow.string_source text )
| _ -> (Http.Response.make ~status:`Not_found (), Cohttp_eio.Body.of_string "")

let () =
let port = ref 8080 in
Arg.parse
[ ("-p", Arg.Set_int port, " Listening port number(8080 by default)") ]
ignore "An HTTP/1.1 server";

Eio_main.run @@ fun env -> Server.run ~port:!port env app
Eio_main.run @@ fun env ->
Eio.Switch.run @@ fun sw ->
let socket =
Eio.Net.listen env#net ~sw ~backlog:128 ~reuse_addr:true
(`Tcp (Eio.Net.Ipaddr.V4.loopback, !port))
and server = Cohttp_eio.Server.make ~callback:handler () in
Cohttp_eio.Server.run socket server ~on_error:raise
Loading

0 comments on commit 6d1c85a

Please sign in to comment.