Skip to content

Commit 731dd7d

Browse files
committed
add a form to echo.ml for manual testing
1 parent 9875543 commit 731dd7d

File tree

2 files changed

+84
-1
lines changed

2 files changed

+84
-1
lines changed

examples/dune

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
(name echo)
1313
(flags :standard -warn-error -a+8)
1414
(modules echo vfs)
15-
(libraries tiny_httpd logs tiny_httpd_camlzip))
15+
(libraries tiny_httpd logs tiny_httpd_camlzip tiny_httpd.multipart-form-data))
1616

1717
(executable
1818
(name writer)

examples/echo.ml

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
open Tiny_httpd_core
22
module Log = Tiny_httpd.Log
3+
module MFD = Tiny_httpd_multipart_form_data
34

45
let now_ = Unix.gettimeofday
56

@@ -78,6 +79,58 @@ let setup_logging () =
7879
Logs.set_reporter @@ Logs.format_reporter ();
7980
Logs.set_level ~all:true (Some Logs.Debug)
8081

82+
let setup_upload server : unit =
83+
Server.add_route_handler_stream ~meth:`POST server
84+
Route.(exact "upload" @/ return)
85+
(fun req ->
86+
let (`boundary boundary) =
87+
match MFD.parse_content_type req.headers with
88+
| Some b -> b
89+
| None -> Response.fail_raise ~code:400 "no boundary found"
90+
in
91+
92+
let st = MFD.create ~boundary req.body in
93+
let tbl = Hashtbl.create 16 in
94+
let cur = ref "" in
95+
let cur_kind = ref "" in
96+
let buf = Buffer.create 16 in
97+
let rec loop () =
98+
match MFD.next st with
99+
| End_of_input ->
100+
if !cur <> "" then
101+
Hashtbl.add tbl !cur (!cur_kind, Buffer.contents buf)
102+
| Part headers ->
103+
if !cur <> "" then
104+
Hashtbl.add tbl !cur (!cur_kind, Buffer.contents buf);
105+
(match MFD.Content_disposition.parse headers with
106+
| Some { kind; name = Some name; filename = _ } ->
107+
cur := name;
108+
cur_kind := kind;
109+
Buffer.clear buf;
110+
loop ()
111+
| _ -> Response.fail_raise ~code:400 "content disposition missing")
112+
| Read sl ->
113+
Buffer.add_subbytes buf sl.bytes sl.off sl.len;
114+
loop ()
115+
in
116+
loop ();
117+
118+
let open Tiny_httpd_html in
119+
let data =
120+
Hashtbl.fold
121+
(fun name (kind, data) acc ->
122+
Printf.sprintf "%S (kind: %S): %S" name kind data :: acc)
123+
tbl []
124+
in
125+
let html =
126+
body []
127+
[
128+
pre []
129+
[ txt (Printf.sprintf "{\n%s\n}" @@ String.concat "\n" data) ];
130+
]
131+
in
132+
Response.make_string ~code:201 @@ Ok (to_string_top html))
133+
81134
let () =
82135
let port_ = ref 8080 in
83136
let j = ref 32 in
@@ -198,6 +251,8 @@ let () =
198251
~dir_behavior:Tiny_httpd.Dir.Index_or_lists ())
199252
~vfs:Vfs.vfs ~prefix:"vfs";
200253

254+
setup_upload server;
255+
201256
(* main page *)
202257
Server.add_route_handler server
203258
Route.(return)
@@ -267,6 +322,34 @@ let () =
267322
txt " (POST) to log out";
268323
];
269324
];
325+
li []
326+
[
327+
form
328+
[
329+
A.action "/upload";
330+
A.enctype "multipart/form-data";
331+
A.target "_self";
332+
A.method_ "POST";
333+
]
334+
[
335+
label [] [ txt "my beautiful form" ];
336+
input [ A.type_ "file"; A.name "file1" ];
337+
input [ A.type_ "file"; A.name "file2" ];
338+
input
339+
[
340+
A.type_ "text";
341+
A.name "a";
342+
A.placeholder "text A";
343+
];
344+
input
345+
[
346+
A.type_ "text";
347+
A.name "b";
348+
A.placeholder "text B";
349+
];
350+
input [ A.type_ "submit" ];
351+
];
352+
];
270353
];
271354
];
272355
]

0 commit comments

Comments
 (0)