You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
letforward (state: State.t) path=match state.save_run with
45
-
|Somesave_run ->
46
-
let fname =Filename.concat save_run path in
47
-
Server.respond_file ~fname()
48
-
|None -> Server.respond_not_found ()
48
+
(* The serving of files is implemented similar as in the binary https://github.com/mirage/ocaml-cohttp/blob/master/cohttp-lwt-unix/bin/cohttp_server_lwt.ml *)
49
+
letserve_file~docroot~uri=
50
+
let fname =Cohttp.Path.resolve_local_file ~docroot~uriin
51
+
Server.respond_file ~fname()
52
+
53
+
letsortlst=
54
+
letcompare_kind=function
55
+
|SomeUnix.S_DIR, SomeUnix.S_DIR -> 0
56
+
|SomeUnix.S_DIR, _ -> -1
57
+
|_, SomeUnix.S_DIR -> 1
58
+
|SomeUnix.S_REG, SomeUnix.S_REG -> 0
59
+
|SomeUnix.S_REG, _ -> 1
60
+
|_, SomeUnix.S_REG -> -1
61
+
|_, _ -> 0in
62
+
List.sort
63
+
(fun (ka, a) (kb, b) ->
64
+
let c = compare_kind (ka, kb) in
65
+
if c <>0then c
66
+
elseString.compare (String.lowercase_ascii a) (String.lowercase_ascii b))
67
+
lst
68
+
69
+
lethtml_of_listinguripathlisting=
70
+
letlil=
71
+
Printf.sprintf "<li><a href=\"%s\">%s</a></li>" (Uri.to_string l) in
72
+
let html =
73
+
List.map
74
+
(fun (kind, f) ->
75
+
let encoded_f =Uri.pct_encode f in
76
+
match kind with
77
+
|SomeUnix.S_DIR ->
78
+
let link =Uri.with_path uri (Filename.concat path (Filename.concat encoded_f "")) in
79
+
li link (Printf.sprintf "<i>%s/</i>" f)
80
+
|SomeUnix.S_REG ->
81
+
let link =Uri.with_path uri (Filename.concat path encoded_f) in
82
+
li link f
83
+
|Some_ ->
84
+
Printf.sprintf "<li><s>%s</s></li>" f
85
+
|None -> Printf.sprintf "<li>Error with file: %s</li>" f)
86
+
listing
87
+
in
88
+
let contents =String.concat "\n" html in
89
+
Printf.sprintf
90
+
"<html><body><h2>Directory Listing for <em>%s</em></h2><ul>%s</ul><hr \
91
+
/></body></html>"
92
+
(Uri.pct_decode path) contents
93
+
94
+
letserveuripath=
95
+
let file_name =Cohttp.Path.resolve_local_file ~docroot:!docroot ~uriin
96
+
Lwt.catch
97
+
(fun() ->
98
+
Lwt_unix.lstat file_name >>=funstat -> (* for symbolic links lstat returns S_LNK, which will result in a
99
+
forbidden error in this implementation. Use stat instead if symbolic links to folders or files should be handled
100
+
just like folders or files respectively *)
101
+
match stat.Unix.st_kind with
102
+
|Unix.S_DIR -> (
103
+
let path_len =String.length path in
104
+
if path_len <>0&& path.[path_len -1] <>'/'then (
105
+
Server.respond_redirect ~uri:(Uri.with_path uri (path ^"/")) ())
106
+
else (
107
+
matchSys.file_exists (Filename.concat file_name !index) with
108
+
|true -> (
109
+
let uri =Uri.with_path uri (Filename.concat path !index) in
110
+
serve_file ~docroot:!docroot ~uri)
111
+
|false ->
112
+
let%lwt files =Lwt_stream.to_list
113
+
(Lwt_stream.filter (funs -> s <>"."&& s <>"..") (Lwt_unix.files_of_directory file_name)) in
114
+
let%lwt listing =Lwt_list.map_s (funf ->
115
+
let file_name =Filename.concat file_name f in
116
+
Lwt.try_bind
117
+
(fun() -> Lwt_unix.LargeFile.stat file_name)
118
+
(funstat ->
119
+
Lwt.return
120
+
( Some
121
+
stat.Unix.LargeFile.st_kind,
122
+
f ))
123
+
(fun_exn -> Lwt.return (None, f))) files in
124
+
let body = html_of_listing uri path (sort listing) in
125
+
Server.respond_string ~status:`OK~body()))
126
+
|Unix.S_REG -> serve_file ~docroot:!docroot ~uri
127
+
|_ -> (
128
+
let body =Printf.sprintf "<html><body><h2>Forbidden</h2><p><b>%s</b> is not a normal file or \
129
+
directory</p><hr/></body></html>" path in
130
+
Server.respond_string ~status:`OK~body()))
131
+
(function
132
+
|Unix.Unix_error (Unix.ENOENT, "stat", p) ase ->
133
+
if p = file_name then (
134
+
Server.respond_not_found ())
135
+
elseLwt.fail e
136
+
|e -> Lwt.fail e)
49
137
50
138
letcallbackstate_reqbody=
51
139
let uri =Request.uri req in
@@ -54,7 +142,7 @@ let callback state _ req body =
54
142
let meth =Request.meth req in
55
143
match meth, parts with
56
144
|`POST, ["api"; name] -> process state name body
57
-
|`GET, _ -> forward state path
145
+
|`GET, _ -> serve uri path
58
146
|_ -> Server.respond_not_found ()
59
147
60
148
letmain()=
@@ -65,6 +153,6 @@ let main () =
65
153
66
154
let()=
67
155
let program =Sys.argv.(0) in
68
-
let usage =Printf.sprintf "%s [-addr ADDR] [-port PORT] ... path [path ...]" program in
156
+
let usage =Printf.sprintf "%s [-docroot DOCROOT] [-index INDEX] [-addr ADDR] [-port PORT] ... path [path ...]" program in
69
157
Arg.parse specs (funs -> paths := s :: !paths) usage;
0 commit comments