Can we directly call a function directly in duct.edn config?
Use case is to override :key parameter to cookie-store in the :duct.middleware.web/defaults {:session {:store cookie-store}}, therefore I want to call (ring.middleware.session.cookie/cookie-store {:key "dummy}) directly in config file. Is it good idea?
Or should we initialize cookie-store in the namespace and pass it like: :duct.middleware.web/defaults {:session {:store : ?
This sounds like a good case for suspend/resume. In development, the key can be randomised, but persist across resets. I'll put together a :duct.session-store/cookie key in the web module to handle this.
In development it would be fine to have randomized key, but in production, key needs to be same across restarts.
Otherwise user logins would invalidate.
Yep. So in production, you could specify the key, but if left blank (as in development) a random key will be chosen that will persist across resets.
There's another way to do this, rather than making another key for this use case, pattern can be described in duct documentation, with separate section.
I don't see a disadvantage to adding a key to automate this common use-case. Do you?
I think more internal keys mean more things to explain when we come across new keys. We can already do same thing by overriding the ring-defaults.
:duct.middleware.web/defaults key in duct's case.
I intend to put the session store key in the :duct.module/web expansion, so for normal usage people won't need to know about it.
:ring.middleware.session.cookie/cookie-store
{:key #ig/var secret-cookie-key}
This pattern initializes cookie-store as singleton?
if we want to call some function more than once, at multiple places, how can we do it ?Yes, the cookie store will be a singleton. If you want multiple, then you need to add multiple keys. Composite keys could be a way to do this, but I'd ideally need to know more about your use-case.
I've been thinking about this a little, and I think it would be a good idea to add this as a configurable option and var to the Duct web module.
Essentially it would add in a var --cookie-store-key (and an environment variable, COOKIE_STORE_KEY) that would allow you to set the cookie store key explicitly in production. In development, you can leave the value blank and the cookie store key will be randomized.
Would something like that work in your particular case?
About composite keys, multiple initialization of a function is something which I think would be useful in general. Like there can be functions which we may want to call more than once in config (currently it allows only singleton, but can be fixed with composite keys)
https://clojurians.slack.com/archives/C52HVRVE1/p1759335940799589
And about cookie store key, that would be better if it goes in the separate config file probably (instead of implicit environment variable), and that file can be merged with main duct.edn file. My use case is that I want to have cookie store key as fixed when server restarts, so in development user doesn't logs out on app restart, and in the production, we can provide it from environment variable.
I think that my use case is fulfilled by :vars key in duct.edn, plus cookie-store initialized in my own namespace, and then called via duct.edn config with key #ig/var from :vars.
I went with latter approach. Thanks.
You'd probably want to add an Integrant key that creates a cookie store. So in your configuration:
:duct.middleware.web/defaults
{:session {:store #ig/ref your.app.session/store}}
:your.app.session/store
{:key #ig/var secret-cookie-key}
And then write your session store:
(ns your.app.session
(:require [ring.middleware.session.cookie :as c]))
(defn store [{:keys [key]}]
(c/cookie-store {:key key}))Though come to think of it, the cookie store fulfils the criteria of being an Integrant init-key function, so you could probably just use it directly:
:duct.middleware.web/defaults
{:session {:store #ig/ref ring.middleware.session.cookie/cookie-store}}
:ring.middleware.session.cookie/cookie-store
{:key #ig/var secret-cookie-key}
I haven't tried it, but in theory that should have the same result, without the need to write your own session store namespace.Just to let you know, I've added a :duct.session-store/cookie key that's automatically included in :duct.module/web. If a key isn't supplied, a secure random key is used. At the REPL, the key is preserved across resets, so you shouldn't have an issue with logging out. In production you can supply a hex-encoded 16 byte key, and if you're load-balancing across multiple servers, they'll need to have the same key in order to read each other's session data.