I’ve been exploring the Dream web framework. It’s a really good introduction to OCaml with easily understandable public types and plenty of examples. Thanks aantron and everyone else who has contributed.
It has built-in CSRF protection for forms which is great, but generating the csrf-code seems to need you to be in a response context (where you would normally be generating your form html). This is not the case when you are testing your Dream site/app though.
I’ve come up with the following to allow me to test forms and wondered if anyone with more experience than myself has a better approach. If not, hopefully this will be searchable for later learners. Oh - at time of writing it is March 2023 and Dream is at 1.0.0 alpha
I have a handlers.ml
with what is presumably the typical one function for each page-handler:
type handler_settings = {
mutable csrf_checking : bool;
}
let settings = { csrf_checking=true }
let app_form req = Dream.form ~csrf:settings.csrf_checking req
(* Below I replaced `Dream.form` with `app_form` *)
let handle_login req =
match%lwt app_form req with
| `Ok [ "password", p; "username", u ] ->
Dream.log "user %s / pass = %s" u p;
...
Page handlers need to remember to call app_form
in place of Dream.form
but otherwise no changes are needed.
Then in the test file we need to make sure CSRF is turned off:
module H = Rota_app.Handlers
let tests = "login", [
Alcotest.test_case "login-successful" `Quick begin fun() ->
H.settings.csrf_checking <- false;
let login_fields = [ "username", "me"; "password", "pass" ] in
let req = make_form_request login_fields in
let handler = H.handle_login in
let res = req |>
Dream.test
@@ Dream.memory_sessions
@@ Dream.flash
@@ handler in
is_redirect_to res "/";
end;
]
The make_form_request
and is_redirect_to
are helper functions that do what you would expect.
I could probably have done something via making Handlers a first-class module or functor or some such but that felt over-engineered for what is currently just one flag for testing. Maybe I’m wrong though - anyone have suggestions?