@@ -116,27 +116,74 @@ let find_static_page ~request ~usermode ~dir ~(err : Cohttp.Code.status)
116116 (Ocsigen_extensions. Error_in_user_config_file
117117 " Staticmod: cannot use '..' in user paths" )
118118
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+
119168let gen ~usermode ?cache dir = function
120169 | Ocsigen_extensions. Req_found _ ->
121170 Lwt. return Ocsigen_extensions. Ext_do_nothing
122171 | Ocsigen_extensions. Req_not_found
123172 (err, ({Ocsigen_extensions. request_info; _} as request)) ->
124173 let try_block () =
125174 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
126179 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
131180 find_static_page ~request ~usermode ~dir ~err ~pathstring
132181 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 ->
140187 let answer = Ocsigen_response. of_cohttp answer in
141188 let answer =
142189 if not status_filter
0 commit comments