1-
21module S = Tiny_httpd
32
43let now_ = Unix. gettimeofday
@@ -22,118 +21,162 @@ let middleware_stat () : S.Middleware.t * (unit -> string) =
2221 total_time_ := ! total_time_ +. (t4 -. t1);
2322 parse_time_ := ! parse_time_ +. (t2 -. t1);
2423 build_time_ := ! build_time_ +. (t3 -. t2);
25- write_time_ := ! write_time_ +. (t4 -. t3);
26- )
24+ write_time_ := ! write_time_ +. (t4 -. t3))
2725 and get_stat () =
28- Printf. sprintf " %d requests (average response time: %.3fms = %.3fms + %.3fms + %.3fms)"
29- ! n_req (! total_time_ /. float ! n_req *. 1e3 )
30- (! parse_time_ /. float ! n_req *. 1e3 )
31- (! build_time_ /. float ! n_req *. 1e3 )
32- (! write_time_ /. float ! n_req *. 1e3 )
26+ Printf. sprintf
27+ " %d requests (average response time: %.3fms = %.3fms + %.3fms + %.3fms)"
28+ ! n_req
29+ (! total_time_ /. float ! n_req *. 1e3 )
30+ (! parse_time_ /. float ! n_req *. 1e3 )
31+ (! build_time_ /. float ! n_req *. 1e3 )
32+ (! write_time_ /. float ! n_req *. 1e3 )
3333 in
3434 m, get_stat
3535
36-
3736let () =
3837 let port_ = ref 8080 in
3938 let j = ref 32 in
40- Arg. parse (Arg. align [
41- " --port" , Arg. Set_int port_, " set port" ;
42- " -p" , Arg. Set_int port_, " set port" ;
43- " --debug" , Arg. Unit (fun () -> S. _enable_debug true ), " enable debug" ;
44- " -j" , Arg. Set_int j, " maximum number of connections" ;
45- ]) (fun _ -> raise (Arg. Bad " " )) " echo [option]*" ;
39+ Arg. parse
40+ (Arg. align
41+ [
42+ " --port" , Arg. Set_int port_, " set port" ;
43+ " -p" , Arg. Set_int port_, " set port" ;
44+ " --debug" , Arg. Unit (fun () -> S. _enable_debug true ), " enable debug" ;
45+ " -j" , Arg. Set_int j, " maximum number of connections" ;
46+ ])
47+ (fun _ -> raise (Arg. Bad " " ))
48+ " echo [option]*" ;
4649
4750 let server = S. create ~port: ! port_ ~max_connections: ! j () in
48- Tiny_httpd_camlzip. setup ~compress_above: 1024 ~buf_size: (16 * 1024 ) server;
51+ Tiny_httpd_camlzip. setup ~compress_above: 1024 ~buf_size: (16 * 1024 ) server;
4952
5053 let m_stats, get_stats = middleware_stat () in
5154 S. add_middleware server ~stage: (`Stage 1 ) m_stats;
5255
5356 (* say hello *)
5457 S. add_route_handler ~meth: `GET server
5558 S.Route. (exact " hello" @/ string @/ return)
56- (fun name _req -> S.Response. make_string (Ok (" hello " ^ name ^ " !\n " )));
59+ (fun name _req -> S.Response. make_string (Ok (" hello " ^ name ^ " !\n " )));
5760
5861 (* compressed file access *)
5962 S. add_route_handler ~meth: `GET server
6063 S.Route. (exact " zcat" @/ string_urlencoded @/ return)
6164 (fun path _req ->
62- let ic = open_in path in
63- let str = S.Byte_stream. of_chan ic in
64- let mime_type =
65+ let ic = open_in path in
66+ let str = S.Byte_stream. of_chan ic in
67+ let mime_type =
68+ try
69+ let p = Unix. open_process_in (Printf. sprintf " file -i -b %S" path) in
6570 try
66- let p = Unix. open_process_in (Printf. sprintf " file -i -b %S" path) in
67- try
68- let s = [" Content-Type" , String. trim (input_line p)] in
69- ignore @@ Unix. close_process_in p;
70- s
71- with _ -> ignore @@ Unix. close_process_in p; []
72- with _ -> []
73- in
74- S.Response. make_stream ~headers: mime_type (Ok str)
75- );
71+ let s = [ " Content-Type" , String. trim (input_line p) ] in
72+ ignore @@ Unix. close_process_in p;
73+ s
74+ with _ ->
75+ ignore @@ Unix. close_process_in p;
76+ []
77+ with _ -> []
78+ in
79+ S.Response. make_stream ~headers: mime_type (Ok str));
7680
7781 (* echo request *)
7882 S. add_route_handler server
7983 S.Route. (exact " echo" @/ return)
8084 (fun req ->
81- let q =
82- S.Request. query req |> List. map (fun (k ,v ) -> Printf. sprintf " %S = %S" k v)
83- |> String. concat " ;"
84- in
85- S.Response. make_string
86- (Ok (Format. asprintf " echo:@ %a@ (query: %s)@." S.Request. pp req q)));
85+ let q =
86+ S.Request. query req
87+ |> List. map (fun (k , v ) -> Printf. sprintf " %S = %S" k v)
88+ |> String. concat " ;"
89+ in
90+ S.Response. make_string
91+ (Ok (Format. asprintf " echo:@ %a@ (query: %s)@." S.Request. pp req q)));
8792
8893 (* file upload *)
8994 S. add_route_handler_stream ~meth: `PUT server
9095 S.Route. (exact " upload" @/ string @/ return)
9196 (fun path req ->
92- S. _debug (fun k ->k " start upload %S, headers:\n %s\n\n %!" path
93- (Format. asprintf " %a" S.Headers. pp (S.Request. headers req)));
94- try
95- let oc = open_out @@ " /tmp/" ^ path in
96- S.Byte_stream. to_chan oc req.S.Request. body;
97- flush oc;
98- S.Response. make_string (Ok " uploaded file" )
99- with e ->
100- S.Response. fail ~code: 500 " couldn't upload file: %s" (Printexc. to_string e)
101- );
97+ S. _debug (fun k ->
98+ k " start upload %S, headers:\n %s\n\n %!" path
99+ (Format. asprintf " %a" S.Headers. pp (S.Request. headers req)));
100+ try
101+ let oc = open_out @@ " /tmp/" ^ path in
102+ S.Byte_stream. to_chan oc req.S.Request. body;
103+ flush oc;
104+ S.Response. make_string (Ok " uploaded file" )
105+ with e ->
106+ S.Response. fail ~code: 500 " couldn't upload file: %s"
107+ (Printexc. to_string e));
102108
103109 (* stats *)
104- S. add_route_handler server S.Route. (exact " stats" @/ return)
110+ S. add_route_handler server
111+ S.Route. (exact " stats" @/ return)
105112 (fun _req ->
106- let stats = get_stats() in
107- S.Response. make_string @@ Ok stats
108- );
113+ let stats = get_stats () in
114+ S.Response. make_string @@ Ok stats);
109115
110116 (* VFS *)
111117 Tiny_httpd_dir. add_vfs server
112- ~config: (Tiny_httpd_dir. config ~download: true
113- ~dir_behavior: Tiny_httpd_dir. Index_or_lists () )
118+ ~config:
119+ (Tiny_httpd_dir. config ~download: true
120+ ~dir_behavior: Tiny_httpd_dir. Index_or_lists () )
114121 ~vfs: Vfs. vfs ~prefix: " vfs" ;
115122
116123 (* main page *)
117- S. add_route_handler server S.Route. (return)
124+ S. add_route_handler server
125+ S.Route. (return)
118126 (fun _req ->
119- let open Tiny_httpd_html in
120- let h = html [] [
121- head[][title[][txt " index of echo" ]];
122- body[][
123- h3[] [txt " welcome!" ];
124- p[] [b[] [txt " endpoints are:" ]];
125- ul[] [
126- li[][pre[][txt " /hello/:name (GET)" ]];
127- li[][pre[][a[A. href " /echo/" ][txt " echo" ]; txt " echo back query" ]];
128- li[][pre[][txt " /upload/:path (PUT) to upload a file" ]];
129- li[][pre[][txt " /zcat/:path (GET) to download a file (deflate transfer-encoding)" ]];
130- li[][pre[][a[A. href " /stats/" ][txt" /stats/" ]; txt" (GET) to access statistics" ]];
131- li[][pre[][a[A. href " /vfs/" ][txt" /vfs" ]; txt" (GET) to access a VFS embedded in the binary" ]];
132- ]
133- ]
134- ] in
135- let s = to_string_top h in
136- S.Response. make_string ~headers: [" content-type" , " text/html" ] @@ Ok s);
127+ let open Tiny_httpd_html in
128+ let h =
129+ html []
130+ [
131+ head [] [ title [] [ txt " index of echo" ] ];
132+ body []
133+ [
134+ h3 [] [ txt " welcome!" ];
135+ p [] [ b [] [ txt " endpoints are:" ] ];
136+ ul []
137+ [
138+ li [] [ pre [] [ txt " /hello/:name (GET)" ] ];
139+ li []
140+ [
141+ pre []
142+ [
143+ a [ A. href " /echo/" ] [ txt " echo" ];
144+ txt " echo back query" ;
145+ ];
146+ ];
147+ li []
148+ [ pre [] [ txt " /upload/:path (PUT) to upload a file" ] ];
149+ li []
150+ [
151+ pre []
152+ [
153+ txt
154+ " /zcat/:path (GET) to download a file (deflate \
155+ transfer-encoding)" ;
156+ ];
157+ ];
158+ li []
159+ [
160+ pre []
161+ [
162+ a [ A. href " /stats/" ] [ txt " /stats/" ];
163+ txt " (GET) to access statistics" ;
164+ ];
165+ ];
166+ li []
167+ [
168+ pre []
169+ [
170+ a [ A. href " /vfs/" ] [ txt " /vfs" ];
171+ txt " (GET) to access a VFS embedded in the binary" ;
172+ ];
173+ ];
174+ ];
175+ ];
176+ ]
177+ in
178+ let s = to_string_top h in
179+ S.Response. make_string ~headers: [ " content-type" , " text/html" ] @@ Ok s);
137180
138181 Printf. printf " listening on http://%s:%d\n %!" (S. addr server) (S. port server);
139182 match S. run server with
0 commit comments