I need to be able to save and restore HT sessions so that they will survive a server restart. Before I dive into this I thought I would ask if anyone has done this already so I don’t reinvent the wheel.
Thanks, rg
Hi Ron,
I haven't done that but it should be a straightforward thing to do.
Just read the section about sessions, look into the code and then you can easily store your sessions objects somewhere.
Best wishes, Daniel
Am 18.01.2014 03:59, schrieb Ron Garret:
I need to be able to save and restore HT sessions so that they will survive a server restart. Before I dive into this I thought I would ask if anyone has done this already so I don’t reinvent the wheel.
Thanks, rg
I find that I have the same requirement and would like not to re-invent wheels so would much appreciate hearing any insights you gained rg.
For local hosting, I used a persistent global session-ID counter as a patch (ensuring session-IDs can't overlap, but that's not acceptable for cloud hosting. All I need really is persistence of the client's cookie validity, as all state data I keep outside HT.
So now I was thinking to modify start-session to be a fork for the make new session case. If the incoming request has no cookie, assume a fresh start so continue as of original start-session, otherwise take this as being an old session, now not found in the session DB. Hence make a replace session.
The session-ID seems irrelevant if I can search of sessions using the session string only. Hence make get-stored-session use string= on the cookie-string.
Ignoring overlapping session-IDs (they begin from 1 each HT boot), I'd need to eliminate reference to session-ID externally and embedded into the cookie string.
But now I get into session-verify etc and expect to run into awkwardnesses. I don't fully understand the use of session-ID, why doesn't HT just use the vanilla cookie-string (without session-ID prefix) ... (despite it obviously being there for some purpose beyond optimized session-DB search). I can't yet get my head around how we can have multiple concurrent sessions to the same client, if that is the original intent. If not then why use the session-id, and why both externally as session-DB index, and internally in the cookie-string as in stringify-session.
peter
At 6:59 PM -0800 14/1/17, Ron Garret wrote:
I need to be able to save and restore HT sessions so that they will survive a server restart. Before I dive into this I thought I would ask if anyone has done this already so I don't reinvent the wheel.
Thanks, rg
On Feb 14, 2014, at 2:31 AM, peter p2.edoc@gmail.com wrote:
I find that I have the same requirement and would like not to re-invent wheels so would much appreciate hearing any insights you gained rg.
Turns out to be very easy. HT sessions can be accessed and set via the generic function ht:session-db, which returns an alist. The alist keys are fixnums and the values are opaque HT::SESSION objects. To make a persistent session all you have to do is serialize and restore this alist. All of the slots of an HT::SESSION are atoms, except for HT::SESSION-DATA, which is an alist, but it contains only values that you put there. So serializing an HT::SESSION is not hard.
The challenging part for me turned out to be restoring Hunchentoot’s internal session state on restart, because HT assumes that there is an active request whenever a session is created:
? (make-instance 'ht::session)
Error: Unbound variable: *REQUEST*
So you have to restore sessions using ALLOCATE-INSTANCE instead of MAKE-INSTANCE. Other than that it is completely straightforward. (I ended up writing a little general-purpose object serializer using the MOP.)
For local hosting, I used a persistent global session-ID counter as a patch (ensuring session-IDs can't overlap, but that's not acceptable for cloud hosting. All I need really is persistence of the client's cookie validity, as all state data I keep outside HT.
Not sure I understand this. HT natively provides unique (per server) session id’s. If you want to make session id’s unique across multiple servers that is a different problem than making sessions persistent. But HT already has a hook for that: the generic function NEXT-SESSION-ID. Is there a reason that doesn’t work for you?
rg
At 8:59 AM -0800 14/2/14, Ron Garret wrote:
On Feb 14, 2014, at 2:31 AM, peter p2.edoc@gmail.com wrote:
I find that I have the same requirement and would like not to re-invent wheels so would much appreciate hearing any insights you gained rg.
Turns out to be very easy. HT sessions can be accessed and set via the generic function ht:session-db, which returns an alist. The alist keys are fixnums and the values are opaque HT::SESSION objects. To make a persistent session all you have to do is serialize and restore this alist. All of the slots of an HT::SESSION are atoms, except for HT::SESSION-DATA, which is an alist, but it contains only values that you put there. So serializing an HT::SESSION is not hard.
The challenging part for me turned out to be restoring Hunchentoot's internal session state on restart, because HT assumes that there is an active request whenever a session is created:
? (make-instance 'ht::session)
Error: Unbound variable: *REQUEST*
So you have to restore sessions using ALLOCATE-INSTANCE instead of MAKE-INSTANCE. Other than that it is completely straightforward. (I ended up writing a little general-purpose object serializer using the MOP.)
For local hosting, I used a persistent global session-ID counter as a patch (ensuring session-IDs can't overlap, but that's not acceptable for cloud hosting. All I need really is persistence of the client's cookie validity, as all state data I keep outside HT.
Not sure I understand this. HT natively provides unique (per server) session id's. If you want to make session id's unique across multiple servers that is a different problem than making sessions persistent. But HT already has a hook for that: the generic function NEXT-SESSION-ID. Is there a reason that doesn't work for you?
We're taking different approaches. Here I am obliged not to make anything persistent in the hunchentoot server file system. So the challenge is to make the cookie itself the only thing that is persistent (so stored in the browser).
My vague plan is:
- ignore the session-ID, use just the cookie-value (as in "0AD9630B5FEA2AEC6E3C24F493B1C0C1") - bypass session-too-old-p for now (later transport the session start time externally to the cookie-value) - so the sequence goes thus:
- incoming url from new client (no cookie) HT makes new session and cookie, and sends cookie back to client - subsequence incoming requests carry a cookie, so handled as usual - re-boot HT (session DB data lost) - original client access (carried cookie) HT has to make a substitute session to serve this client
hence ignore the session ID throughout, and search the session DB using the cookie value, as in:
(defun get-stored-session (cookie-value) (cdr (assoc cookie-value (session-db *acceptor*) :test #'string= :key 'session-string)))
Now I'll have to promulgate the consequences of this shift from managing session by ID to cookie-value.
But I'm worried that I've overlooked something. Why wasn't this approach (indexing session by cookie-value instead of session-ID do in the first place). I.e. I fear there must be a good reason what session-IDs were used. Unless there was a need to prevent session persistence.
I am cowering in anticipation of receiving a castigation for missing the most obvious thing. But persistent session without using any local file store is my requirement.
peter
But Peter is right that there is no need to presist attributes your application associate with user session via hunchentoot mechanism. You can just store the attributes your application intorduces in your own DB, using sessionID as a subkey.
The Ron's solution ensures another aspect - when hunchentoot is restarted, the same sessions will remain to be active.
If Peter wants this too, he needs to persist information needed to handle session timeouts.
So, the approaches are not so different.
14.02.2014, 22:18, "peter" p2.edoc@gmail.com:
But I'm worried that I've overlooked something. Why wasn't this approach (indexing session by cookie-value instead of session-ID do in the first place). I.e. I fear there must be a good reason what session-IDs were used.
session-ID is a cookie value
At 10:28 PM +0400 14/2/14, Anton Vodonosov wrote:
14.02.2014, 22:18, "peter" p2.edoc@gmail.com:
But I'm worried that I've overlooked something. Why wasn't this approach (indexing session by cookie-value instead of session-ID do in the first place). I.e. I fear there must be a good reason what session-IDs were used.
session-ID is a cookie value
i appreciate that (it is prepended to the md5-hex part of the cookie). and it is a convenient way to index sessions DB in HT. however beyond that, i see no purpose for it. and in the case of making sessions persistent without saving any state on the HT system, they seem irrelevant and need to be side-stepped. hence why i am trying to index the session DB using the md5-hex part of the cookie only.