AJAX Requests Get And Set Cookies Like Any Other HTTP Request

Posted August 25, 2010 at 11:03 AM by Ben Nadel

Tags: Javascript / DHTML

Sometimes, people ask me how to handle session management within an application that makes AJAX requests. A question like this can mean many different things; but often times, after a little discussion, I discover that this question is based on a fundamental misunderstanding of what an AJAX request actually is. Because we are so used to the request-response life cycle, there is something almost magical about an AJAX request that runs in parallel to the page processing; heck, I use them all the time and I still get a jolt of delight at seeing them work. In reality, however, there is nothing magical about them; in fact, they work exactly like every other HTTP request.

Because HTTP is an inherently stateless protocol, we generally rely on cookies to maintain the state of a user's session across multiple HTTP requests. However, since there is still a bit of mystery surrounding AJAX requests, people are sometimes not sure as to whether or not cookies play nicely with AJAX. But, once you accept the fact that an AJAX request is an HTTP request, it becomes a no-brainer that cookies get sent back and forth in the AJAX request-response headers.

To demonstrate this functionality, I have put together a little ColdFusion demo that executes an AJAX request and outputs the cookies that the AJAX request posted to the server. And, to show that cookies can be both send and set, I am also generating a new cookie with each AJAX request.

I have tested this demo in the following browsers:

  • Firefox
  • Chrome
  • Safari
  • Opera
  • IE 6,7,8

Here is the server-side page that is responding to the incoming AJAX request:

Get.cfm (AJAX End Point)

  • <!---
  • Create a response that outputs all of the cookies currently
  • passed in from the AJAX request. In ColdFusion, the cookie
  • collection is populated by the request headers.
  • --->
  • <cfsavecontent variable="responseText">
  • <cfoutput>
  •  
  • <h3>
  • Cookies ( as of #timeFormat( now(), "hh:mm:ss" )# )
  • </h3>
  •  
  • <ul>
  • <!--- Loop over the cookie collection. --->
  • <cfloop
  • item="key"
  • collection="#cookie#">
  •  
  • <!--- Only output cookies relevant to this test. --->
  • <cfif reFindNoCase( "^rand", key )>
  •  
  • <li>
  • #key# : #cookie[ key ]#
  • </li>
  •  
  • </cfif>
  •  
  • </cfloop>
  • </ul>
  •  
  • </cfoutput>
  • </cfsavecontent>
  •  
  •  
  • <!---
  • Now that we've created the cookie output, let's create a random
  • cookie to set in the current AJAX request. This will get sent
  • back to the client as Set-Cookie header.
  • --->
  • <cfcookie
  • name="rand#randRange( 111, 999 )#"
  • value="Woot!"
  • />
  •  
  •  
  • <!--- Return the HTML response to the client. --->
  • <cfcontent
  • type="text/html"
  • variable="#toBinary( toBase64( responseText ) )#"
  • />

As you can see, this ColdFusion code is simply echoing back (in HTML format) the cookie collection that the AJAX request has posted. And, to demonstrate that cookies can also be set from within an AJAX request, I am generating a new cookie with the CFCookie tag.

Here is the test HTML page that is making the AJAX request:

  • <!DOCTYPE html>
  • <html>
  • <head>
  • <title>AJAX And Cookies</title>
  • <script type="text/javascript">
  •  
  • // I took this right out of the jQuery source. It creates a
  • // cross-browser way of creating XHR request objects.
  • var xhr = (
  • (
  • window.XMLHttpRequest &&
  • (window.location.protocol !== "file:" || !window.ActiveXObject)
  • ) ?
  • function() {
  • return new window.XMLHttpRequest();
  • } :
  • function() {
  • try {
  • return new window.ActiveXObject("Microsoft.XMLHTTP");
  • } catch(e) {}
  • }
  • );
  •  
  •  
  • // I test the AJAX request for cookie transporation.
  • function testAjax(){
  • // Create a new XHR request object.
  • var request = xhr();
  •  
  • // Open the AJAX connection.
  • request.open(
  • "GET",
  • ("./get.cfm?_=" + (new Date()).getTime()),
  • false
  • );
  •  
  • // Send the request. Since this request is being made
  • // *Synchronously*, we don't have to keep a ready-state
  • // change handler.
  • request.send();
  •  
  • // Get a handle on the output node.
  • var output = document.getElementById( "output" );
  •  
  • // Append output HTML.
  • output.innerHTML += request.responseText;
  • }
  •  
  • </script>
  • </head>
  • <body>
  •  
  • <h1>
  • AJAX And Cookies
  • </h1>
  •  
  • <div id="output">
  • <!-- To be populated with AJAX. -->
  • </div>
  •  
  • <p id="tools">
  • <a
  • href="#tools"
  • onclick="testAjax();"
  • >Test AJAX Request</a>
  • </p>
  •  
  • </body>
  • </html>

As you can see, all we're doing here is making a AJAX request and appending the HTML response to the page. In this way, we can see how the collection of cookies gets mutated over time.

NOTE: I am making a synchronous request, rather than an asynchronous request, such that I don't have to worry about a ReadyState change handler.

After clicking the "Test AJAX Request" link a few times, here is the page output that I get:

 
 
 
 
 
 
AJAX Requests Send And Set Cookies Just Like Any Other HTTP Request. 
 
 
 

As you can see, the collection of cookies is being augmented with every single AJAX request. This clearly demonstrates that AJAX requests both send the existing cookie collection and correctly respond to Set-Cookie headers within the AJAX response.

I believe that there are ways to make cookies explicitly unavailable for AJAX requests; I think IE has a proprietary "HTTPOnly" attribute or something - I know very little about that. But, other than that and a few IFrame bugs, I hope this demonstration makes people feel a little more comfortable using session management in the context of AJAX requests. Just remember - AJAX requests are HTTP requests.




Reader Comments

Aug 25, 2010 at 11:18 AM // reply »
34 Comments

Ben,

Good post. Yeah a lot of use take this for granted and already know it, but when you are on a team which is new to AJAX these type of articles are great.

Also could see your code being adapted to a nice testing feature (when firebug or the like not available), so double nice post :)


Aug 25, 2010 at 11:49 AM // reply »
70 Comments

@Ben: Of course, the most important cookies of all are JSessionId or CFID and CFToken. But they don't do any good unless the AJAX callback does a cfapplication with the correct name attribute to restore the session scope. When people ask you how to handle session management, they may have tried and failed due to that other side of the coin. Just a thought.


Aug 25, 2010 at 3:06 PM // reply »
149 Comments

cfapplication whaaaaaaaaatttt?

* alarm sounds *


Aug 25, 2010 at 3:42 PM // reply »
11,238 Comments

@Kevin,

Thanks my man. And, as much as I was pretty sure it worked this way - I definitely did some good cross-browser testing to make sure I wasn't crazy :)

@Steve,

That's a good point - session tokens only work well if you are in the right application name space. I've seen code from time to time where the name of the application was dynamic and actually changed on every page request. It's clearly a bug in the code, but the person doing this had no idea what it was happening.

@David,

Ha ha :P


Aug 27, 2010 at 12:42 AM // reply »
1 Comments

When people ask you how to handle session management, they may have tried and failed due to that other side of the coin. Just a thought.Thanks for sharing this blog with us.


Sep 4, 2010 at 11:13 AM // reply »
11,238 Comments

@Newquay,

You definitely have a good point. I assume that is probably what is happening some of the time; but, it's good to cover all the bases.


May 4, 2012 at 11:47 AM // reply »
1 Comments

Hi ben, nice article. But is there a way to know which all cookies are being set from the javascript? because response.getResponseHeader("Set-Cookie") returns null.


Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 19, 2013 at 2:31 PM
My Experience With AngularJS - The Super-heroic JavaScript MVW Framework
It's funny really just how well that image describes the way I would imagine most people that go with angular for some project is. I have had a similar roller-coaster ride with it as well, but not qu ... read »
May 17, 2013 at 7:42 PM
HashKeyCopier - An AngularJS Utility Class For Merging Cached And Live Data
Ben - thanks so much for posting these Angular articles and findings, they've been a huge help towards learning one of the more 'complex' JavaScript frameworks out there (IMO). I have been using Angu ... read »
May 16, 2013 at 5:01 PM
UPDATE: Parsing CSV Data Files In ColdFusion With csvToArray()
Your code was the closest thing I've found to obtaining some direction for converting ISO fields to values that CF can translate properly. Thank you for posting! ... read »
May 15, 2013 at 10:37 PM
Very Simple Pusher And ColdFusion Powered Chat
hi id making plz easy ... read »
May 15, 2013 at 6:07 PM
Making SOAP Web Service Requests With ColdFusion And CFHTTP
Ben, you once again saved my bacon at work. Thank you, thank you, thank you! ... read »
May 15, 2013 at 4:15 PM
What If All User Interface (UI) Data Came In Reports?
@Josh, Thanks! @Ben, I definitely recommend the David West book "Object Thinking" I've been quoting from. It goes deeply into the philosophy and history of OO programming. His breadth ... read »
May 15, 2013 at 11:36 AM
Ask Ben: Print Part Of A Web Page With jQuery
I found this helpfull when you need to keep (refresh) the original parent page after closing the iframe child print dialog (Hoping you're not using a form at this time so it won't submit again): On ... read »
May 14, 2013 at 7:13 PM
What If All User Interface (UI) Data Came In Reports?
@Jonah, If there's any books you'd recommend on the subject of domain modelling, I'd love to hear it. I just downloaded the free PDF of "Domain Driven Design Quickly". Figured I'd give it ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools