Adding a cookie in an ajax request

447 views
Skip to first unread message

j...@joescii.com

unread,
Dec 19, 2017, 5:08:35 PM12/19/17
to Lift
I'm attempting to add a cookie during an ajax request handler via S.addCookie but I'm not able to get it to work as expected. I have pushed a sample project branch showing what I am trying to do. The app is just an index page with a form to let you set an arbitrary cookie. The submission is printed in the application console as well as the browser console to show the round trip. 

The S.addCookie works if I set it somewhere like LiftRules.earlyInStateful where I would expect the cookie to be set during the initial request. Seems like it's just not working in ajax calls which I wouldn't have expected.

This is my form [github]:
<form data-lift="form.ajax">
<div data-lift="CookieForm">
<input type="text" name="name"/>
<input type="text" name="value"/>
<button>Add Cookie</button>
</div>
</form>

This is my snippet (omitting imports) [github]: 
object CookieForm {
def render = {
var name: String = ""
var value: String = ""

def process(): JsCmd = {
val cookie = HTTPCookie(name, value)

println(s"Adding cookie $cookie")
S.addCookie(cookie)
println(S.responseCookies)
JsRaw(s"console.log('Added cookie: $name = $value')")
}

"name=name" #> SHtml.text(name, name = _) &
"name=value" #> (SHtml.text(value, value = _) ++ SHtml.hidden(process))
}
}

Everything checks out except I never see the cookie set in the Chrome developer tools. Refreshing the page doesn't get it done either. I've tried with both Lift 3.1 and Lift 2.6.

Do we have a bug, or do I have a misunderstanding? 

Joe

Antonio Salazar Cardozo

unread,
Dec 20, 2017, 4:35:47 PM12/20/17
to Lift
My guess is a bug. Tracing what happens to `S.responseCookies` during the JS response
processing pipeline (via LiftSession's `runParams`) is probably the way to go.
Thanks,
Antonio

Joe Barnes

unread,
Dec 26, 2017, 10:10:45 AM12/26/17
to lif...@googlegroups.com
Cool Antonio! I'll investigate what the disconnect is when I get some time.

Joe
 

/**
 * Joe Barnes
 * Owner/Principal Consultant, joescii, llc
 */


--
--
Lift, the simply functional web framework: http://liftweb.net
Code: http://github.com/lift
Discussion: http://groups.google.com/group/liftweb
Stuck? Help us help you: https://www.assembla.com/wiki/show/liftweb/Posting_example_code

---
You received this message because you are subscribed to the Google Groups "Lift" group.
To unsubscribe from this group and stop receiving emails from it, send an email to liftweb+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Joe Barnes

unread,
Jan 2, 2018, 6:20:43 PM1/2/18
to lif...@googlegroups.com
I've been poking around on the code today, and I don't see anything out of place. The cookies are stored in a ThreadGlobal within S. The main thing I've noticed is if I add a cookie in the main request handling pipeline, that cookie sticks around for the session (and gets set in the browser as well). But if I add a cookie in an ajax handling thread, the cookie is added to the ThreadGlobal but seems only for the life of that particular request. It never appears in the browser.

This feels like two bugs to me. 1) One is that a cookie added in an ajax handler does not stick to the session, but only to the request. 2) Secondly I would expect the response to the ajax call to update the cookies in the browser. I suspect that cookie is not added to the ajax response (which should just work). If only (1) was a problem, then refreshing the page after setting a cookie in ajax should result in the browser having the cookie set. If only (2) was a problem, I would be seeing cookies in the browser that Lift isn't remembering in later requests.

I welcome any thoughts about what I've observed and concluded thus far. 

Thanks! 
Joe



/**
 * Joe Barnes
 * Owner/Principal Consultant, joescii, llc
 */


Matt Farmer

unread,
Jan 3, 2018, 10:13:26 AM1/3/18
to lif...@googlegroups.com
I vaguely remember dealing with something like this in the past. Can you snoop the Ajax response from the network tab in the debugging tools and verify that the cookie actually gets sent?
To unsubscribe from this group and stop receiving emails from it, send an email to liftweb+u...@googlegroups.com.

Joe Barnes

unread,
Jan 3, 2018, 5:52:41 PM1/3/18
to lif...@googlegroups.com
Yep, that's exactly what I ended up doing. It turned out that you must set the path to "/" for a cookie to be set as expected from an ajax response. Hence, this is now my cookie: 

val cookie = HTTPCookie(name, value).copy(path = Full("/"))

For my purposes, this works. The cookie is set in the browser as expected, and is included in subsequent calls back to my Lift server in the Cookie header.

Going back to my original analysis, we still have inconsistent behavior due to what I called "bug 1". Because Lift isn't remembering this cookie, only this ajax response sets it. Cookies that I've added with something like LiftRules.earlyInStateful are included in a set-cookie header on every request from the Lift server.

I feel like this is a "don't-care" sort of thing. The set-cookie header only needs to be sent once. In fact, that's how jetty handles setting JSESSIONID. Only the first request has it set. Unless someone has some ideas on how to make this better, I'm gonna leave Lift as-is.

Joe



/**
 * Joe Barnes
 * Owner/Principal Consultant, joescii, llc
 */


Reply all
Reply to author
Forward
0 new messages