aantron / dream

Tidy, feature-complete Web framework
https://aantron.github.io/dream/
MIT License
1.59k stars 126 forks source link

Flash message usage? #307

Open dbp opened 9 months ago

dbp commented 9 months ago

I'm wondering if I've missed how to use the flash messages, or if. there is some incompatibility with cookie sessions, or...?

I have a (pretty small) application set up as:

Dream.set_log_level "dream.flash" `Debug;
  Dream.run ~interface:"0.0.0.0"
  @@ Dream.logger
  @@ Dream.set_secret (Sys.getenv "COOKIE_KEY")
  @@ Dream.flash
  @@ Dream.cookie_sessions
  @@ Dream.router [
...

In one handler, I set a message and redirect:

let () = Dream.add_flash_message request "Access" "You do not have access to that" in Dream.redirect request "/"

And in the handler for "/", I render them using the snippet from the example. But in the log, it seems like they are gone by the redirect:

09.12.23 22:20:29.068     dream.flash DEBUG REQ 1 Flash messages: Access: You do not have access to that
09.12.23 22:20:29.074       dream.log  INFO REQ 1 303 / in 7954 μs
09.12.23 22:20:29.076       dream.log  INFO REQ 2 GET / 127.0.0.1:62941 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_156
09.12.23 22:20:29.077     dream.flash DEBUG REQ 2 No flash messages.

Is there some configuration I am missing?

aantron commented 9 months ago

The basic flash example seems to work with cookie_sessions, at least for me locally. Could you provide an example that can be compiled, to observe this issue?

dbp commented 9 months ago

It seems like it is an interaction between the flash messages and Dream.get "/**". Here is a reproduction, I changed the flash example to:

let result request =
  <html>
  <body>

%   Dream.flash_messages request |> List.iter (fun (category, text) ->
      <p><%s category %>: <%s text %></p><% ); %>

  </body>
  </html>

let set_flash_middleware handler request =
  Dream.add_flash_message request "Info" "Hello!";
  handler request

let () =
  Dream.set_log_level "dream.flash" `Debug;
  Dream.run
  @@ Dream.logger
  @@ Dream.flash
  @@ Dream.cookie_sessions
  @@ Dream.router [

    Dream.get  "/"
      (fun request ->
        Dream.html (result request));

    Dream.scope "/set" [set_flash_middleware] [
      Dream.get "/**" (fun request -> Dream.redirect request "/")
    ];

  ]

And the log becomes:

12.12.23 14:18:04.285       dream.log  INFO REQ 2 GET /set/ 127.0.0.1:53358 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
12.12.23 14:18:04.288     dream.flash DEBUG REQ 2 Flash messages: Info: Hello!
12.12.23 14:18:04.293       dream.log  INFO REQ 2 303 / in 7638 μs
12.12.23 14:18:04.295       dream.log  INFO REQ 3 GET / 127.0.0.1:53358 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
12.12.23 14:18:04.295     dream.flash DEBUG REQ 3 No flash messages.
12.12.23 14:18:04.302       dream.log  INFO REQ 3 200 in 6174 μs

(I am using this to have access controlled static file serving... so I have middleware that authenticates, sets a flash message and redirects if not authenticated).

aantron commented 9 months ago

Looks like the flash message cookie is transmitted with a Path=/set attribute if ** is used. That seems wrong but I'll have to look into why it's like that. At first glance it looks like I changed the semantics of one of my helpers at some point, essentially reusing its name for a completely different purpose (site prefixes for multiple sites sharing a doman vs. the already-matched path prefix in the router), but I'll have to carefully check all the implications before fixing it. Thanks for the repro case!