@@ -116,27 +116,74 @@ let find_static_page ~request ~usermode ~dir ~(err : Cohttp.Code.status)
116
116
(Ocsigen_extensions. Error_in_user_config_file
117
117
" Staticmod: cannot use '..' in user paths" )
118
118
119
+ let respond_dir relpath dname : (Cohttp.Response.t * Cohttp_lwt.Body.t) Lwt.t =
120
+ let readsortdir =
121
+ (* Read a complete directory and sort its entries *)
122
+ let chunk_size = 1024 in
123
+ let rec aux entries dir =
124
+ Lwt_unix. readdir_n dir chunk_size >> = fun chunk ->
125
+ let entries = chunk :: entries in
126
+ if Array. length chunk < chunk_size
127
+ then Lwt. return entries
128
+ else aux entries dir
129
+ in
130
+ Lwt_unix. opendir dname >> = fun dir ->
131
+ Lwt. finalize
132
+ (fun () ->
133
+ aux [] dir > |= fun entries ->
134
+ List. sort compare (List. concat_map Array. to_list entries))
135
+ (fun () -> Lwt_unix. closedir dir)
136
+ in
137
+ Lwt. catch
138
+ (fun () ->
139
+ readsortdir >> = fun entries ->
140
+ let render e = Format. asprintf " %a" (Tyxml.Html. pp_elt () ) e in
141
+ let t = render (Tyxml.Html. txt (" Directory listing for " ^ relpath)) in
142
+ let entries =
143
+ let open Tyxml.Html in
144
+ List. filter_map
145
+ (function
146
+ | "." | ".." -> None
147
+ | e -> Some (render (li [a ~a: [a_href e] [txt e]])))
148
+ entries
149
+ in
150
+ (* Chunks of [html (head (title t) []) (body [h1 [t]; ul entries])] *)
151
+ let chunk1 =
152
+ {|<! DOCTYPE html>
153
+ < html xmlns= " http://www.w3.org/1999/xhtml" >< head>< title> | }
154
+ and chunk2 = {|</ title>< / head>< body>< h1> | }
155
+ and chunk3 = {|</ h1>< ul> | }
156
+ and chunkend = {|</ ul>< / body>< / html> | } in
157
+ let doc =
158
+ chunk1 :: t :: chunk2 :: t :: chunk3 :: (entries @ [chunkend])
159
+ in
160
+ let headers = Cohttp.Header. init_with " content-type" " text/html" in
161
+ Lwt. return
162
+ ( Cohttp.Response. make ~status: `OK ~headers ()
163
+ , Cohttp_lwt.Body. of_string_list doc ))
164
+ (function
165
+ | Unix. Unix_error _ -> Cohttp_lwt_unix.Server. respond_not_found ()
166
+ | exn -> Lwt. fail exn )
167
+
119
168
let gen ~usermode ?cache dir = function
120
169
| Ocsigen_extensions. Req_found _ ->
121
170
Lwt. return Ocsigen_extensions. Ext_do_nothing
122
171
| Ocsigen_extensions. Req_not_found
123
172
(err, ({Ocsigen_extensions. request_info; _} as request)) ->
124
173
let try_block () =
125
174
Lwt_log. ign_info ~section " Is it a static file?" ;
175
+ let pathstring =
176
+ Ocsigen_lib.Url. string_of_url_path ~encode: false
177
+ (Ocsigen_request. sub_path request_info)
178
+ in
126
179
let status_filter, page =
127
- let pathstring =
128
- Ocsigen_lib.Url. string_of_url_path ~encode: false
129
- (Ocsigen_request. sub_path request_info)
130
- in
131
180
find_static_page ~request ~usermode ~dir ~err ~pathstring
132
181
in
133
- let fname =
134
- match page with
135
- | Ocsigen_local_files. RFile fname -> fname
136
- | Ocsigen_local_files. RDir _ ->
137
- failwith " FIXME: staticmod dirs not implemented"
138
- in
139
- Cohttp_lwt_unix.Server. respond_file ~fname () >> = fun answer ->
182
+ (match page with
183
+ | Ocsigen_local_files. RFile fname ->
184
+ Cohttp_lwt_unix.Server. respond_file ~fname ()
185
+ | Ocsigen_local_files. RDir dname -> respond_dir pathstring dname)
186
+ >> = fun answer ->
140
187
let answer = Ocsigen_response. of_cohttp answer in
141
188
let answer =
142
189
if not status_filter
0 commit comments