Skip to content

Commit a92253f

Browse files
committed
flash messages: discuss API calls, Fetch "omit" cookies
1 parent 7871b07 commit a92253f

File tree

1 file changed

+54
-1
lines changed

1 file changed

+54
-1
lines changed

content/building-blocks/flash-messages.md

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,18 @@ For this, we use Hunchentoot's life cycle and CLOS-orientation:
9999
(ht:delete-session-value :flash))
100100
```
101101

102-
which means: after we have handled the current request, delete the `:flash` object from the session.
102+
which means: after we have handled a request, delete the
103+
`:flash` object from the session.
104+
105+
{{% notice warning %}}
106+
107+
If your application sends API requests in JavaScript, they can delete flash messages without you noticing. Read more below.
108+
109+
An external API request (from the command line for example) is not
110+
concerned, as it doesn't carry Hunchentoot session cookies.
111+
112+
{{% /notice %}}
113+
103114

104115
## Render flash messages in templates
105116

@@ -269,3 +280,45 @@ you'll see a flash message, that is deleted after use.
269280
Refresh the page, and you won't see the flash message again.
270281

271282
- full code: https://github.com/web-apps-in-lisp/web-apps-in-lisp.github.io/blob/master/content/building-blocks/flash-messages.lisp
283+
284+
## Discussing: Flash messages and API calls
285+
286+
Our `:after` method on the Hunchentoot request lifecycle will delete
287+
flash messages for any request that carries the session cookies. If
288+
your application makes API calls, you can use the Fetch method with
289+
the `{credentials: "omit"}` parameter:
290+
291+
~~~javascript
292+
fetch("http://localhost:9876/api/", {
293+
credentials: "omit"
294+
})
295+
~~~
296+
297+
Otherwise, don't use this `:after` method and delete flash messages
298+
explicitely in your non-API routes.
299+
300+
We could use a macro shortcut for this:
301+
302+
303+
~~~lisp
304+
(defmacro with-flash-messages ((messages) &body body)
305+
`(let ((,messages (ht:session-value :flash)))
306+
(prog1
307+
(progn
308+
,@body)
309+
(ht:delete-session-value :flash))))
310+
~~~
311+
312+
Use it like this:
313+
314+
~~~lisp
315+
(easy-routes:defroute flash-route ("/flash/" :method :get) ()
316+
(with-flash-messages (messages)
317+
(djula:render-template* *flash-template* nil
318+
:flashes (or messages
319+
(list (cons "is-primary" "No more flash messages were found in the session. This is a default notification."))))))
320+
~~~
321+
322+
We want our macro to return the result of `djula:render-template*`,
323+
and *not* the result of `ht:delete-session-value`, that is nil, hence
324+
the "prog1/ progn" dance.

0 commit comments

Comments
 (0)