1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
module FileString = struct
let size = 16_000
let s = Bytes.make size '\000'
let b = Buffer.create size
let read_file ic =
Buffer.clear b;
let rec iter ic b s =
let nread = input ic s 0 size in
if nread > 0 then begin
Buffer.add_subbytes b s 0 nread;
iter ic b s
end
in
iter ic b s;
Buffer.contents b
let read_file filename =
let ic = open_in_bin filename in
try
let s = read_file ic in
close_in ic;
s
with e ->
close_in ic;
raise e
end
let normalize_path path =
let rec normalize_path path revpath =
match path, revpath with
| [],_ -> List.rev revpath
| ("" | ".") :: path, _ -> normalize_path path revpath
| ".." :: path, _ :: revpath -> normalize_path path revpath
| ".." :: path, [] -> normalize_path path []
| dir :: path, revpath -> normalize_path path (dir :: revpath)
in
normalize_path path []
let rec reply ?(meth=`GET) ?default root path =
let path = normalize_path path in
let file = Filename.concat root (String.concat "/" path) in
let content_type = EzAPI.Mime.content_type_of_file file in
match meth with
| `OPTIONS ->
if Sys.file_exists file then
Lwt.return {Answer.code = 200; body = ""; headers = ["access-control-allow-methods", "GET"]}
else begin match default with
| None ->
Lwt.return {Answer.code = 404; body = ""; headers = []}
| Some file ->
reply ~meth root (String.split_on_char '/' file)
end
| _ ->
let body = FileString.read_file file in
EzDebug.printf "Returning file %S of length %d" file
(String.length body);
Lwt.return {Answer.code = 200; body; headers = ["content-type", content_type]}