[OCaml] Mobile-friendly clone of cgit.
1
(** Serving the static assets embedded at build time.
2
3
Assets are compiled into the executable by [ocaml-crunch] (see the rule in
4
[lib/dune]), so a deployment is a single binary with no asset directory to
5
keep in sync. Responses are cached for a day; because the content ships with
6
the binary, a new release is the only thing that can change them.
7
8
TODO: the cache lifetime is hard-coded. Make it configurable, or switch to
9
content-hashed asset URLs so the lifetime can be raised safely. *)
10
11
let content_type_of_ext = function
12
| ".css" -> "text/css; charset=utf-8"
13
| ".svg" -> "image/svg+xml"
14
| ".html" -> "text/html; charset=utf-8"
15
| ".js" -> "application/javascript"
16
| ".png" -> "image/png"
17
| ".ico" -> "image/x-icon"
18
| _ -> "application/octet-stream"
19
20
let handler request =
21
let target = Dream.target request in
22
(* Strip "/static/" prefix *)
23
let path =
24
if String.starts_with ~prefix:"/static/" target then
25
String.sub target 8 (String.length target - 8)
26
else ""
27
in
28
match Static_assets.read path with
29
| Some content ->
30
let content_type = Filename.extension path |> content_type_of_ext in
31
Dream.respond
32
~headers:
33
[
34
("Content-Type", content_type);
35
("Cache-Control", "public, max-age=86400");
36
]
37
content
38
| None -> Dream.respond ~status:`Not_Found "Not found"
39