[OCaml] High Intensity Training Online
fix Preserve navigation on authenticated errors
Resolve the current viewer in the catch-all route and pass the viewer and request to error_page. Authenticated 404 pages now render the same top navigation and profile menu as other authenticated pages. Public errors keep the public shell.
Changed files
lib/web/handlers.ml
@@ -1614,14 +1614,25 @@
1614
1614
body Dream's router would return. Kept last so it never shadows a real
1615
1615
route. The production [error_handler] covers the rest: [5xx] responses and
1616
1616
uncaught exceptions. *)
1617
Removed:
let catch_all =
1618
Removed:
Dream.any "/**" (fun _ ->
1619
Removed:
html ~status:`Not_Found (Pages.error_page ~status:404))
1617
Added:
let catch_all t =
1618
Added:
Dream.any "/**" (fun request ->
1619
Added:
current_trainee t request >>= function
1620
Added:
| Some trainee ->
1621
Added:
let viewer =
1622
Added:
{
1623
Added:
View_model.Viewer.username =
1624
Added:
Trainee.username_to_string trainee.Trainee.username;
1625
Added:
}
1626
Added:
in
1627
Added:
html ~status:`Not_Found
1628
Added:
(Pages.error_page ~viewer ~request ~status:404 ())
1629
Added:
| None -> html ~status:`Not_Found (Pages.error_page ~status:404 ()))
1620
1630
1621
1631
let routes t =
1622
1632
Auth.routes t @ Overview.routes t @ Current_workout.routes t
1623
1633
@ Logbook.routes t @ App_feedback.routes t @ Profile.routes t
1624
Removed:
@ Settings.routes t @ Import.routes t @ Assets.routes @ [ catch_all ]
1634
Added:
@ Settings.routes t @ Import.routes t @ Assets.routes
1635
Added:
@ [ catch_all t ]
1625
1636
1626
1637
(* A branded error page for every failure Dream routes here: unmatched paths,
1627
1638
[4xx] and [5xx] responses, and uncaught exceptions. The page names only the
@@ -1630,6 +1641,6 @@
1630
1641
let error_handler =
1631
1642
Dream.error_template (fun _error _message suggested ->
1632
1643
let status = Dream.status suggested |> Dream.status_to_int in
1633
Removed:
Dream_html.set_body suggested (Pages.error_page ~status);
1644
Added:
Dream_html.set_body suggested (Pages.error_page ~status ());
1634
1645
Lwt.return suggested)
1635
1646
end
lib/web/pages.ml
@@ -262,7 +262,7 @@
262
262
of failure, never a server-supplied string, so nothing internal leaks. The
263
263
navigation stays present — top on desktop, bottom on mobile — so a lost
264
264
visitor is one tap from a known destination. *)
265
Removed:
let error_page ~status =
265
Added:
let error_page ?viewer ?request ~status () =
266
266
let title, detail =
267
267
match status with
268
268
| 404 ->
@@ -273,7 +273,7 @@
273
273
("Something went wrong", "The server hit a problem. Try again shortly.")
274
274
| _ -> ("Something went wrong", "That request could not be completed.")
275
275
in
276
Removed:
html_page ~show_nav:true title
276
Added:
html_page ?viewer ?request ~show_nav:true title
277
277
[
278
278
tag "p" [ class_ "eyebrow" ] [ txt "%d" status ];
279
279
tag "h1" [] [ txt "%s" title ];
lib/web/pages.mli
@@ -102,7 +102,12 @@
102
102
103
103
val problem : title:string -> detail:string -> page
104
104
105
Removed:
val error_page : status:int -> page
105
Added:
val error_page :
106
Added:
?viewer:View_model.Viewer.t ->
107
Added:
?request:Dream.request ->
108
Added:
status:int ->
109
Added:
unit ->
110
Added:
page
106
111
(** A branded page for an HTTP failure. It names only the class of failure, so
107
112
no server-supplied string leaks, and keeps the navigation affordances: top
108
113
on desktop, bottom on mobile. *)