This commit is contained in:
parent
aa2ff7b2f0
commit
2f3113f55d
11742 changed files with 1223940 additions and 0 deletions
9
unikernel/duniverse/httpun/examples/eio/dune
Normal file
9
unikernel/duniverse/httpun/examples/eio/dune
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
(executables
|
||||
(libraries httpun httpun-eio httpun_examples base stdio eio_main eio-ssl)
|
||||
(names eio_echo_post eio_get eio_ssl_get)
|
||||
(flags :standard -warn-error -A))
|
||||
|
||||
(alias
|
||||
(name examples)
|
||||
(deps
|
||||
(glob_files *.exe)))
|
||||
87
unikernel/duniverse/httpun/examples/eio/eio_echo_post.ml
Normal file
87
unikernel/duniverse/httpun/examples/eio/eio_echo_post.ml
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
open Base
|
||||
module Arg = Stdlib.Arg
|
||||
|
||||
open Httpun_eio
|
||||
open Httpun
|
||||
|
||||
let error_handler (_ : Eio.Net.Sockaddr.stream) = Httpun_examples.Server.error_handler
|
||||
|
||||
let request_handler ~u (_ : Eio.Net.Sockaddr.stream) { Gluten.reqd; _ } =
|
||||
match Reqd.request reqd with
|
||||
| { Request.meth = `POST; headers; _ } ->
|
||||
let response =
|
||||
let content_type =
|
||||
match Headers.get headers "content-type" with
|
||||
| None -> "application/octet-stream"
|
||||
| Some x -> x
|
||||
in
|
||||
Response.create
|
||||
~headers:(Headers.of_list
|
||||
[ "content-type", content_type;
|
||||
"transfer-encoding", "chunked"
|
||||
(* ; "connection", "close" *)
|
||||
]) `OK
|
||||
in
|
||||
let request_body = Reqd.request_body reqd in
|
||||
let response_body = Reqd.respond_with_streaming reqd response in
|
||||
let rec on_read buffer ~off ~len =
|
||||
Body.Writer.write_bigstring response_body buffer ~off ~len;
|
||||
Body.Reader.schedule_read request_body ~on_eof ~on_read;
|
||||
and on_eof () =
|
||||
Stdlib.Format.eprintf "EOF@.";
|
||||
Body.Writer.close response_body;
|
||||
Eio.Promise.resolve_ok u ()
|
||||
in
|
||||
Body.Reader.schedule_read (Reqd.request_body reqd) ~on_eof ~on_read
|
||||
| _ ->
|
||||
let headers = Headers.of_list [ "connection", "close" ] in
|
||||
Reqd.respond_with_string reqd (Response.create ~headers `Method_not_allowed) ""
|
||||
;;
|
||||
|
||||
|
||||
let log_connection_error ex =
|
||||
Eio.traceln "Uncaught exception handling client: %a" Fmt.exn ex
|
||||
|
||||
let main port =
|
||||
Eio_main.run (fun env ->
|
||||
let listen_address = (`Tcp (Eio.Net.Ipaddr.V4.loopback, port)) in
|
||||
let network = Eio.Stdenv.net env in
|
||||
let handler ~u =
|
||||
Server.create_connection_handler ~request_handler:(request_handler ~u) ~error_handler in
|
||||
Eio.Switch.run (fun sw ->
|
||||
let socket =
|
||||
Eio.Net.listen ~reuse_addr:true ~reuse_port:true ~backlog:5 ~sw
|
||||
network
|
||||
listen_address
|
||||
in
|
||||
Stdio.printf "Listening on port %i and echoing POST requests.\n" port;
|
||||
Stdio.printf "To send a POST request, try one of the following\n\n";
|
||||
Stdio.printf " echo \"Testing echo POST\" | dune exec examples/async/async_post.exe\n";
|
||||
Stdio.printf " echo \"Testing echo POST\" | dune exec examples/lwt/lwt_post.exe\n";
|
||||
Stdio.printf " echo \"Testing echo POST\" | curl -XPOST --data @- http://localhost:%d\n\n%!" port;
|
||||
let domain_mgr = Eio.Stdenv.domain_mgr env in
|
||||
let p, _ = Eio.Promise.create () in
|
||||
for _i = 1 to Stdlib.Domain.recommended_domain_count () do
|
||||
Eio.Fiber.fork_daemon ~sw (fun () ->
|
||||
Eio.Domain_manager.run domain_mgr (fun () ->
|
||||
Eio.Switch.run (fun sw ->
|
||||
while true do
|
||||
Eio.Net.accept_fork socket ~sw ~on_error:log_connection_error (fun client_sock client_addr ->
|
||||
let p, u = Eio.Promise.create () in
|
||||
handler ~sw ~u client_addr client_sock;
|
||||
Eio.Promise.await_exn p)
|
||||
done;
|
||||
`Stop_daemon)))
|
||||
done;
|
||||
Eio.Promise.await p));
|
||||
|
||||
;;
|
||||
|
||||
let () =
|
||||
let port = ref 8080 in
|
||||
Arg.parse
|
||||
["-p", Arg.Set_int port, " Listening port number (8080 by default)"]
|
||||
ignore
|
||||
"Echoes POST requests. Runs forever.";
|
||||
main !port
|
||||
;;
|
||||
70
unikernel/duniverse/httpun/examples/eio/eio_get.ml
Normal file
70
unikernel/duniverse/httpun/examples/eio/eio_get.ml
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
module Arg = Stdlib.Arg
|
||||
|
||||
open Httpun
|
||||
|
||||
let handler ~on_eof response response_body =
|
||||
match response with
|
||||
| { Response.status = `OK; _ } as response ->
|
||||
Format.fprintf Format.std_formatter "%a\n%!" Response.pp_hum response;
|
||||
let rec on_read bs ~off ~len =
|
||||
Bigstringaf.substring ~off ~len bs |> print_string;
|
||||
flush stdout;
|
||||
Body.Reader.schedule_read response_body ~on_read ~on_eof
|
||||
in
|
||||
Body.Reader.schedule_read response_body ~on_read ~on_eof;
|
||||
| response ->
|
||||
Format.fprintf Format.err_formatter "%a\n%!" Response.pp_hum response;
|
||||
Stdlib.exit 124
|
||||
;;
|
||||
|
||||
let main port host =
|
||||
Eio_main.run (fun _env ->
|
||||
Eio.Switch.run (fun sw ->
|
||||
let fd = Unix.socket ~cloexec:true Unix.PF_INET Unix.SOCK_STREAM 0 in
|
||||
let addrs =
|
||||
Eio_unix.run_in_systhread (fun () ->
|
||||
Unix.getaddrinfo
|
||||
host
|
||||
(Int.to_string port)
|
||||
[ Unix.(AI_FAMILY PF_INET) ])
|
||||
in
|
||||
Eio_unix.run_in_systhread (fun () ->
|
||||
Unix.connect fd (List.hd addrs).ai_addr);
|
||||
let socket = Eio_unix.Net.import_socket_stream ~sw ~close_unix:true fd in
|
||||
let headers = Headers.of_list [ "host", host ] in
|
||||
let connection =
|
||||
Httpun_eio.Client.create_connection ~sw socket
|
||||
in
|
||||
|
||||
let exit_cond = Eio.Condition.create () in
|
||||
let response_handler =
|
||||
handler ~on_eof:(fun () ->
|
||||
Stdlib.Format.eprintf "eof@.";
|
||||
Eio.Condition.broadcast exit_cond)
|
||||
in
|
||||
let request_body =
|
||||
Httpun_eio.Client.request
|
||||
(* ~flush_headers_immediately:true *)
|
||||
~error_handler:Httpun_examples.Client.error_handler
|
||||
~response_handler
|
||||
connection
|
||||
(Request.create ~headers `GET "/")
|
||||
in
|
||||
Body.Writer.close request_body;
|
||||
Eio.Condition.await_no_mutex exit_cond;
|
||||
Httpun_eio.Client.shutdown connection |> Eio.Promise.await))
|
||||
|
||||
let () =
|
||||
let host = ref None in
|
||||
let port = ref 80 in
|
||||
Arg.parse
|
||||
["-p", Set_int port, " Port number (80 by default)"]
|
||||
(fun host_argument -> host := Some host_argument)
|
||||
"lwt_get.exe [-p N] HOST";
|
||||
let host =
|
||||
match !host with
|
||||
| None -> failwith "No hostname provided"
|
||||
| Some host -> host
|
||||
in
|
||||
main !port host
|
||||
;;
|
||||
89
unikernel/duniverse/httpun/examples/eio/eio_ssl_get.ml
Normal file
89
unikernel/duniverse/httpun/examples/eio/eio_ssl_get.ml
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
module Arg = Stdlib.Arg
|
||||
|
||||
open Httpun
|
||||
|
||||
module Client = Httpun_eio.Client
|
||||
|
||||
let () =
|
||||
Ssl.init ~thread_safe:true ()
|
||||
|
||||
let handler ~on_eof response response_body =
|
||||
match response with
|
||||
| { Response.status = `OK; _ } as response ->
|
||||
Format.fprintf Format.std_formatter "%a\n%!" Response.pp_hum response;
|
||||
let rec on_read _bs ~off:_ ~len:_ =
|
||||
(* Bigstringaf.substring ~off ~len bs |> print_string; *)
|
||||
Body.Reader.schedule_read response_body ~on_read ~on_eof
|
||||
in
|
||||
Body.Reader.schedule_read response_body ~on_read ~on_eof;
|
||||
| response ->
|
||||
Format.fprintf Format.err_formatter "%a\n%!" Response.pp_hum response;
|
||||
Stdlib.exit 124
|
||||
;;
|
||||
|
||||
let main port host =
|
||||
Eio_main.run (fun env ->
|
||||
Eio.Switch.run (fun sw ->
|
||||
let addrs =
|
||||
let addrs =
|
||||
Eio_unix.run_in_systhread (fun () ->
|
||||
Unix.getaddrinfo
|
||||
host
|
||||
(string_of_int port)
|
||||
[ Unix.(AI_FAMILY PF_INET) ])
|
||||
in
|
||||
List.filter_map
|
||||
(fun (addr : Unix.addr_info) ->
|
||||
match addr.ai_addr with
|
||||
| Unix.ADDR_UNIX _ -> None
|
||||
| ADDR_INET (addr, port) -> Some (addr, port))
|
||||
addrs
|
||||
in
|
||||
let addr =
|
||||
let inet, port = List.hd addrs in
|
||||
`Tcp (Eio_unix.Net.Ipaddr.of_unix inet, port)
|
||||
in
|
||||
let socket = Eio.Net.connect ~sw (Eio.Stdenv.net env) addr in
|
||||
let ctx = Ssl.create_context (Ssl.SSLv23 [@ocaml.warning "-3"]) Ssl.Client_context in
|
||||
Ssl.disable_protocols ctx [ (Ssl.SSLv23 [@ocaml.warning "-3"]) ];
|
||||
Ssl.honor_cipher_order ctx;
|
||||
Ssl.set_context_alpn_protos ctx [ "h2" ];
|
||||
let ssl_ctx = Eio_ssl.Context.create ~ctx socket in
|
||||
let ssl_sock = Eio_ssl.Context.ssl_socket ssl_ctx in
|
||||
Ssl.set_client_SNI_hostname ssl_sock host;
|
||||
Ssl.set_hostflags ssl_sock [ No_partial_wildcards ];
|
||||
Ssl.set_host ssl_sock host;
|
||||
let ssl_sock = Eio_ssl.connect ssl_ctx in
|
||||
|
||||
let headers = Headers.of_list [ "host", host ] in
|
||||
let connection = Client.create_connection ~sw ssl_sock in
|
||||
let response_handler =
|
||||
handler ~on_eof:(fun () ->
|
||||
Stdlib.Format.eprintf "eof@.";
|
||||
Client.shutdown connection |> Eio.Promise.await)
|
||||
in
|
||||
let request_body =
|
||||
Client.request
|
||||
connection
|
||||
~flush_headers_immediately:true
|
||||
~error_handler:Httpun_examples.Client.error_handler
|
||||
~response_handler
|
||||
(Request.create ~headers `GET "/")
|
||||
in
|
||||
Body.Writer.close request_body));
|
||||
;;
|
||||
|
||||
let () =
|
||||
let host = ref None in
|
||||
let port = ref 443 in
|
||||
Arg.parse
|
||||
["-p", Set_int port, " Port number (80 by default)"]
|
||||
(fun host_argument -> host := Some host_argument)
|
||||
"lwt_get.exe [-p N] HOST";
|
||||
let host =
|
||||
match !host with
|
||||
| None -> failwith "No hostname provided"
|
||||
| Some host -> host
|
||||
in
|
||||
main !port host
|
||||
;;
|
||||
Loading…
Add table
Add a link
Reference in a new issue