Skip to content

Commit 687da09

Browse files
authored
Merge pull request #116 from Linda-Njau/server-error
Show detailed diagnostics for 500 server errors
2 parents 5a8fca9 + d15ebd3 commit 687da09

20 files changed

Lines changed: 285 additions & 14 deletions

CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,12 @@
8484

8585
#### Yocaml_unix
8686

87+
- Improve rendering of 500 error pages on server (by [Linda-Njau](https://github.com/Linda-Njau))
8788
- Adapt runtime to `is_file` (by [xvw](https://xvw.lol))
8889

8990
#### Yocaml_eio
9091

92+
- Improve rendering of 500 error pages on server (by [Linda-Njau](https://github.com/Linda-Njau))
9193
- Adapt runtime to `is_file` (by [xvw](https://xvw.lol))
9294

9395
#### Yocaml_git

lib/core/runtime.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ module Make (Runtime : Required.RUNTIME) = struct
2222
~in_exception_handler:true)
2323
exn
2424
in
25-
msg |> Runtime.log `Error |> Runtime.bind (fun () -> raise Exit)
25+
msg |> Runtime.log `Error |> Runtime.bind (fun () -> raise exn)
2626

2727
let runtimec error =
2828
let error = Runtime.runtime_error_to_string error in

lib/runtime/server.ml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@ module Pages = struct
107107
|> String.concat ""
108108
in
109109
Format.asprintf "<nav><h1>%s</h1></nav><ul>%s</ul>" top listing
110+
111+
let error500 msg =
112+
Format.asprintf
113+
"<h1>500 Internal server error</h1><hr /><p>The build failed while \
114+
refreshing the site.</p><pre>%s</pre>"
115+
msg
110116
end
111117

112118
let prompt port =

lib/runtime/server.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ module Pages : sig
5454

5555
val error404 : string -> string
5656
val directory : string list -> Kind.t list -> string
57+
val error500 : string -> string
5758
end
5859

5960
(** {1 Helpers} *)

plugins/yocaml_eio/server.ml

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,22 @@ let dir path lpath =
6060
render_html @@ Yocaml_runtime.Server.Pages.directory lpath children
6161

6262
let handler htdoc refresh _socket request _body =
63-
let () = refresh () in
64-
match get_requested_uri htdoc request with
65-
| Error404 -> error404 htdoc
66-
| File (path, str) -> file path str
67-
| Dir (path, lpath) -> dir path lpath
63+
try
64+
refresh ();
65+
match get_requested_uri htdoc request with
66+
| Error404 -> error404 htdoc
67+
| File (path, str) -> file path str
68+
| Dir (path, lpath) -> dir path lpath
69+
with exn ->
70+
let msg =
71+
Format.asprintf "%a"
72+
(fun ppf exn ->
73+
Yocaml.Diagnostic.exception_to_diagnostic ~in_exception_handler:true
74+
ppf exn)
75+
exn
76+
in
77+
render_html ~status:`Internal_server_error
78+
(Yocaml_runtime.Server.Pages.error500 msg)
6879

6980
let run ?custom_error_handler directory port program env =
7081
Eio.Switch.run (fun sw ->

plugins/yocaml_unix/server.ml

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,22 @@ let dir reqd path lpath =
8282

8383
let[@warning "-8"] handler htdoc refresh _socket
8484
(`V1 reqd : Httpcats.Server.reqd) =
85-
let () = refresh () in
86-
match get_requested_uri htdoc reqd with
87-
| Error404 -> error404 reqd htdoc
88-
| File (path, _) -> file reqd path
89-
| Dir (path, lpath) -> dir reqd path lpath
85+
try
86+
refresh ();
87+
match get_requested_uri htdoc reqd with
88+
| Error404 -> error404 reqd htdoc
89+
| File (path, _) -> file reqd path
90+
| Dir (path, lpath) -> dir reqd path lpath
91+
with exn ->
92+
let msg =
93+
Format.asprintf "%a"
94+
(fun ppf exn ->
95+
Yocaml.Diagnostic.exception_to_diagnostic ~in_exception_handler:true
96+
ppf exn)
97+
exn
98+
in
99+
render_html ~status:`Internal_server_error reqd
100+
(Yocaml_runtime.Server.Pages.error500 msg)
90101

91102
let run ?custom_error_handler directory port program =
92103
let refresh () = Runner.run ?custom_error_handler program in

test/e2e/bin/dune

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,25 @@
2929
yocaml_jingoo
3030
yocaml_cmarkit
3131
yocaml_markdown))
32+
33+
(executable
34+
(name unix_server_error)
35+
(modules server_error unix_server_error test_article)
36+
(libraries
37+
yocaml
38+
yocaml_unix
39+
yocaml_yaml
40+
yocaml_jingoo
41+
yocaml_cmarkit
42+
yocaml_markdown))
43+
44+
(executable
45+
(name eio_server_error)
46+
(modules server_error eio_server_error test_article)
47+
(libraries
48+
yocaml
49+
yocaml_eio
50+
yocaml_yaml
51+
yocaml_jingoo
52+
yocaml_cmarkit
53+
yocaml_markdown))

test/e2e/bin/eio_server_error.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
let () =
2+
let port, resolver, file = Server_error.setup () in
3+
Yocaml_eio.serve ~target:resolver#target ~port
4+
(Server_error.program resolver file)

test/e2e/bin/server_error.ml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
module Test_Article = Test_article
2+
3+
class resolver ~source ~target =
4+
object (self)
5+
val get_source : Yocaml.Path.t = source
6+
val get_target : Yocaml.Path.t = target
7+
method source = get_source
8+
method target = Yocaml.Path.(get_target / "_www")
9+
method cache = Yocaml.Path.(self#target / ".cache")
10+
method templates = Yocaml.Path.(self#source / "content" / "templates")
11+
method articles = Yocaml.Path.(self#target / "articles")
12+
13+
method as_article path =
14+
path
15+
|> Yocaml.Path.move ~into:self#articles
16+
|> Yocaml.Path.change_extension "html"
17+
18+
method as_template path = Yocaml.Path.(self#templates / path)
19+
end
20+
21+
let article (resolver : resolver) file =
22+
Yocaml.Action.Static.write_file_with_metadata (resolver#as_article file)
23+
Yocaml.Task.(
24+
Yocaml_yaml.Pipeline.read_file_with_metadata (module Test_Article) file
25+
>>> Yocaml_cmarkit.content_to_html ()
26+
>>> Yocaml_jingoo.Pipeline.as_template
27+
(module Test_Article)
28+
(resolver#as_template "article.html")
29+
>>> Yocaml_jingoo.Pipeline.as_template
30+
(module Test_Article)
31+
(resolver#as_template "layout.html"))
32+
33+
let program (resolver : resolver) file () =
34+
Yocaml.Action.with_cache ~on:`Target resolver#cache (article resolver file)
35+
36+
let setup () =
37+
let port, file =
38+
match Array.to_list Sys.argv with
39+
| _ :: port_str :: file :: _ -> (int_of_string port_str, file)
40+
| _ -> failwith "Usage: server_error.exe <port> <file>"
41+
in
42+
let cwd = Yocaml.Path.rel [] in
43+
let file = Yocaml.Path.rel [ file ] in
44+
let resolver = new resolver ~source:cwd ~target:cwd in
45+
(port, resolver, file)

test/e2e/bin/unix_server_error.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
let () =
2+
let port, resolver, file = Server_error.setup () in
3+
Yocaml_unix.serve ~target:resolver#target ~port
4+
(Server_error.program resolver file)

0 commit comments

Comments
 (0)