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
open Riot
module Conn = Connection
open Riot.Logger.Make (struct
let namespace = [ "trail"; "static" ]
end)
type args = { root : string; prefix : string }
type state = args
let init args = args
let call (conn : Conn.t) { root; prefix } =
let rel_path = conn.req.path |> String.concat Stdlib.Filename.dir_sep in
debug (fun f -> f "serving file at %S" rel_path);
if String.starts_with ~prefix rel_path then (
let abs_path = Stringext.replace_all rel_path ~pattern:prefix ~with_:root in
let stat = File.stat abs_path in
let file = File.open_read abs_path in
let reader = File.to_reader file in
let data =
Bytestring.with_bytes ~capacity:stat.st_size (IO.read reader)
|> Result.get_ok
in
File.close file;
let mime_type = Magic_mime.lookup abs_path in
conn
|> Conn.with_header "content-type" mime_type
|> Conn.send_response `OK data)
else conn