ocaml http/1, http/2 and websocket client and server library
1open Alcotest
2
3let find_header name headers =
4 let name = String.lowercase_ascii name in
5 List.find_map
6 (fun (k, v) -> if String.lowercase_ascii k = name then Some v else None)
7 headers
8
9let client_error_to_string = function
10 | Hcs.Client.Connection_failed s -> "Connection_failed: " ^ s
11 | Hcs.Client.Tls_error s -> "Tls_error: " ^ s
12 | Hcs.Client.Protocol_error s -> "Protocol_error: " ^ s
13 | Hcs.Client.Timeout -> "Timeout"
14 | Hcs.Client.Invalid_response s -> "Invalid_response: " ^ s
15 | Hcs.Client.Too_many_redirects -> "Too_many_redirects"
16
17let h2_error_to_string = function
18 | Hcs.H2_client.Connection_failed s -> "Connection_failed: " ^ s
19 | Hcs.H2_client.Tls_error s -> "Tls_error: " ^ s
20 | Hcs.H2_client.Protocol_error s -> "Protocol_error: " ^ s
21 | Hcs.H2_client.Timeout -> "Timeout"
22 | Hcs.H2_client.Invalid_response s -> "Invalid_response: " ^ s
23
24let run_server ~sw ~net ~clock ~port ~protocol =
25 let handler (req : Hcs.Server.request) =
26 let value =
27 match find_header "x-default" req.headers with
28 | Some v -> v
29 | None -> "missing"
30 in
31 Hcs.Server.respond value
32 in
33
34 let server_config =
35 Hcs.Server.
36 {
37 default_config with
38 host = "127.0.0.1";
39 port;
40 protocol;
41 gc_tuning = None;
42 }
43 in
44
45 Eio.Fiber.fork_daemon ~sw (fun[@warning "-21"] () ->
46 Hcs.Server.run ~sw ~net ~config:server_config handler;
47 `Stop_daemon);
48
49 Eio.Time.sleep clock 0.05
50
51let test_default_headers_are_sent_h1 () =
52 Eio_main.run @@ fun env ->
53 Eio.Switch.run @@ fun sw ->
54 let net = Eio.Stdenv.net env in
55 let clock = Eio.Stdenv.clock env in
56
57 let port = 18000 + (Unix.getpid () mod 1000) in
58 run_server ~sw ~net ~clock ~port ~protocol:Hcs.Server.Http1_only;
59
60 let client_config =
61 Hcs.Client.default_config
62 |> Hcs.Client.with_default_header "X-Default" "yes"
63 in
64
65 match
66 Hcs.Client.get ~sw ~net ~clock ~config:client_config
67 (Printf.sprintf "http://127.0.0.1:%d/" port)
68 with
69 | Error e -> Alcotest.fail ("request failed: " ^ client_error_to_string e)
70 | Ok resp -> Alcotest.(check string) "x-default header" "yes" resp.body
71
72let test_default_headers_are_sent_h2 () =
73 Eio_main.run @@ fun env ->
74 Eio.Switch.run @@ fun sw ->
75 let net = Eio.Stdenv.net env in
76 let clock = Eio.Stdenv.clock env in
77
78 let port = 19000 + (Unix.getpid () mod 1000) in
79 run_server ~sw ~net ~clock ~port ~protocol:Hcs.Server.Http2_only;
80
81 let config =
82 Hcs.H2_client.default_config
83 |> Hcs.H2_client.with_default_header "x-default" "yes"
84 in
85
86 match
87 Hcs.H2_client.get' ~sw ~net ~clock ~config
88 (Printf.sprintf "http://127.0.0.1:%d/" port)
89 with
90 | Error e -> Alcotest.fail ("request failed: " ^ h2_error_to_string e)
91 | Ok resp ->
92 let body = resp.Hcs.H2_client.body in
93 Alcotest.(check string) "x-default header" "yes" body
94
95let () =
96 run "Hcs.Client default headers"
97 [
98 ( "default_headers",
99 [
100 test_case "sent (h1)" `Quick test_default_headers_are_sent_h1;
101 test_case "sent (h2)" `Quick test_default_headers_are_sent_h2;
102 ] );
103 ]