|
| 1 | +(* Dates *) |
| 2 | + |
| 3 | +let get_date () = Unix.(gettimeofday () |> gmtime) |
| 4 | + |
| 5 | +let dow = function |
| 6 | + | 0 -> "Sun" |
| 7 | + | 1 -> "Mon" |
| 8 | + | 2 -> "Tue" |
| 9 | + | 3 -> "Wed" |
| 10 | + | 4 -> "Thu" |
| 11 | + | 5 -> "Fri" |
| 12 | + | _ -> "Sat" |
| 13 | + |
| 14 | +let month = function |
| 15 | + | 0 -> "Jan" |
| 16 | + | 1 -> "Feb" |
| 17 | + | 2 -> "Mar" |
| 18 | + | 3 -> "Apr" |
| 19 | + | 4 -> "May" |
| 20 | + | 5 -> "Jun" |
| 21 | + | 6 -> "Jul" |
| 22 | + | 7 -> "Aug" |
| 23 | + | 8 -> "Sep" |
| 24 | + | 9 -> "Oct" |
| 25 | + | 10 -> "Nov" |
| 26 | + | _ -> "Dec" |
| 27 | + |
| 28 | +let date () = |
| 29 | + let d = get_date () in |
| 30 | + (* Wed, 17 Apr 2013 12:00:00 GMT *) |
| 31 | + Format.sprintf "%s, %02d %s %4d %02d:%02d:%02d GMT" (dow d.tm_wday) d.tm_mday |
| 32 | + (month d.tm_mon) (1900 + d.tm_year) d.tm_hour d.tm_min d.tm_sec |
| 33 | + |
| 34 | +(* HTTP *) |
| 35 | + |
| 36 | +let _plaintext date reqd = |
| 37 | + let open H1 in |
| 38 | + let payload = "Hello, World!" in |
| 39 | + let headers = |
| 40 | + Headers.of_rev_list |
| 41 | + [ ("content-length", string_of_int (String.length payload)) |
| 42 | + ; ("content-type", "text/plain") |
| 43 | + ; ("server", "httpcats") |
| 44 | + ; ("date", !date) ] in |
| 45 | + let resp = Response.create ~headers `OK in |
| 46 | + Reqd.respond_with_string reqd resp payload |
| 47 | + |
| 48 | +let _json date reqd = |
| 49 | + let open H1 in |
| 50 | + let obj = `Assoc [ ("message", `String "Hello, World!") ] in |
| 51 | + let payload = Yojson.to_string obj in |
| 52 | + let headers = |
| 53 | + Headers.of_rev_list |
| 54 | + [ ("content-length", string_of_int (String.length payload)) |
| 55 | + ; ("content-type", "application/json") |
| 56 | + ; ("server", "httpcats") |
| 57 | + ; ("date", !date) ] in |
| 58 | + let resp = Response.create ~headers `OK in |
| 59 | + Reqd.respond_with_string reqd resp payload |
| 60 | + |
| 61 | +let _not_found reqd = |
| 62 | + let open H1 in |
| 63 | + let moo = "m00." in |
| 64 | + let headers = |
| 65 | + Headers.of_rev_list |
| 66 | + [ "content-length", string_of_int (String.length moo) ] in |
| 67 | + let resp = Response.create ~headers `OK in |
| 68 | + Reqd.respond_with_string reqd resp moo |
| 69 | + |
| 70 | +let[@warning "-8"] handler date _ |
| 71 | + (`V1 reqd : [ `V1 of H1.Reqd.t | `V2 of H2.Reqd.t ]) = |
| 72 | + let open H1 in |
| 73 | + let request = Reqd.request reqd in |
| 74 | + match request.Request.target with |
| 75 | + | "/plaintext" -> _plaintext date reqd |
| 76 | + | "/json" -> _json date reqd |
| 77 | + | _ -> _not_found reqd |
| 78 | + |
| 79 | +let localhost_8080 = Unix.(ADDR_INET (inet_addr_any, 8080)) |
| 80 | + |
| 81 | +let server stop = |
| 82 | + let cell = ref (date ()) in |
| 83 | + let prm = Miou.async @@ fun () -> |
| 84 | + Miou_unix.sleep 1.; |
| 85 | + cell := date () in |
| 86 | + let handler = handler cell in |
| 87 | + Httpcats.Server.clear ~parallel:false ~stop ~backlog:4096 ~handler localhost_8080; |
| 88 | + Miou.cancel prm |
| 89 | + |
| 90 | +let () = Sys.set_signal Sys.sigpipe Sys.Signal_ignore |
| 91 | + |
| 92 | +let run () = |
| 93 | + let domains = |
| 94 | + Unix.open_process_in "getconf _NPROCESSORS_ONLN" |
| 95 | + |> input_line |> int_of_string in |
| 96 | + Miou_unix.run ~domains @@ fun () -> |
| 97 | + let stop = Httpcats.Server.stop () in |
| 98 | + let fn _sigint = Httpcats.Server.switch stop in |
| 99 | + ignore (Miou.sys_signal Sys.sigint (Sys.Signal_handle fn)); |
| 100 | + let domains = Miou.Domain.available () in |
| 101 | + let prm = Miou.async @@ fun () -> server stop in |
| 102 | + if domains > 0 then |
| 103 | + Miou.parallel server (List.init domains (Fun.const stop)) |
| 104 | + |> List.iter (function Ok () -> () | Error exn -> raise exn); |
| 105 | + Miou.await_exn prm |
| 106 | + |
| 107 | +let () = Unix.handle_unix_error run () |
0 commit comments