diff --git a/examples/echo.ml b/examples/echo.ml index 9c39b0f0..94939263 100644 --- a/examples/echo.ml +++ b/examples/echo.ml @@ -1,6 +1,28 @@ module S = Tiny_httpd +let now_ = Unix.gettimeofday + +(* util: a little middleware collecting statistics *) +let middleware_stat () : S.Middleware.t * (unit -> string) = + let n_req = ref 0 in + let total_time_ = ref 0. in + + let m h req ~resp = + incr n_req; + let t1 = now_ () in + h req ~resp:(fun response -> + resp response; + let t2 = now_ () in + total_time_ := !total_time_ +. (t2 -. t1); + ) + and get_stat () = + Printf.sprintf "%d requests (average response time: %.3fs)" + !n_req (!total_time_ /. float !n_req) + in + m, get_stat + + let () = let port_ = ref 8080 in let j = ref 32 in @@ -10,12 +32,19 @@ let () = "--debug", Arg.Unit (fun () -> S._enable_debug true), " enable debug"; "-j", Arg.Set_int j, " maximum number of connections"; ]) (fun _ -> raise (Arg.Bad "")) "echo [option]*"; + let server = S.create ~port:!port_ ~max_connections:!j () in Tiny_httpd_camlzip.setup ~compress_above:1024 ~buf_size:(16*1024) server; + + let m_stats, get_stats = middleware_stat () in + S.add_middleware server ~stage:(`Stage 1) m_stats; + (* say hello *) S.add_route_handler ~meth:`GET server S.Route.(exact "hello" @/ string @/ return) (fun name _req -> S.Response.make_string (Ok ("hello " ^name ^"!\n"))); + + (* compressed file access *) S.add_route_handler ~meth:`GET server S.Route.(exact "zcat" @/ string_urlencoded @/ return) (fun path _req -> @@ -33,6 +62,7 @@ let () = in S.Response.make_stream ~headers:mime_type (Ok str) ); + (* echo request *) S.add_route_handler server S.Route.(exact "echo" @/ return) @@ -43,6 +73,8 @@ let () = in S.Response.make_string (Ok (Format.asprintf "echo:@ %a@ (query: %s)@." S.Request.pp req q))); + + (* file upload *) S.add_route_handler_stream ~meth:`PUT server S.Route.(exact "upload" @/ string @/ return) (fun path req -> @@ -56,6 +88,28 @@ let () = with e -> S.Response.fail ~code:500 "couldn't upload file: %s" (Printexc.to_string e) ); + + (* stats *) + S.add_route_handler server S.Route.(exact "stats" @/ return) + (fun _req -> + let stats = get_stats() in + S.Response.make_string @@ Ok stats + ); + + (* main page *) + S.add_route_handler server S.Route.(return) + (fun _req -> + let s = "\n\ +

welcome!\n

endpoints are:\n

" + in + S.Response.make_string ~headers:["content-type", "text/html"] @@ Ok s); + Printf.printf "listening on http://%s:%d\n%!" (S.addr server) (S.port server); match S.run server with | Ok () -> ()