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 »
69 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 »
134 Comments

cfapplication whaaaaaaaaatttt?

* alarm sounds *


Aug 25, 2010 at 3:42 PM // reply »
10,638 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 »
10,638 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.


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
InVision App - Prototyping Made Beautiful With Prototyping Tools Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
Feb 3, 2012 at 10:49 PM
How I Got Node.js Running On A Linux Micro Instance Using Amazon EC2
Wow this was really helpful! Only thing I would add is you need to update your .bash_profile after you edit the secure_path. This is what I did: $ . ~/.bash_profile Otherwise, NPM won't be found. ... read »
Feb 3, 2012 at 10:14 PM
Pushing Base64-Encoded Images Over HTML5 WebSockets With Pusher And ColdFusion
@Ben, Just wanted to let you know that pusher are soon to start limiting sizes on messages. This was the detail that came through in the Feb dispatch: "However, we will soon be limiting the s ... read »
Feb 3, 2012 at 5:05 PM
Regular Expressions Make CSV Parsing In ColdFusion So Much Easier (And Faster)
I tried using your RegEx in my C# program, but it was matching an extra empty-string at the end and so I would end up with an extra field that doesn't exist, so I changed it to this: (^|,)("(?: ... read »
Feb 3, 2012 at 3:47 PM
ColdFusion Supports HTTP Verbs PUT And DELETE (As Well As GET And POST)
Josh Cyr posted this on Twitter just a little bit ago. Thought it was appropriate. http://stackoverflow.com/questions/1619152/how-to-create-rest-urls-without-verbs/1619677#1619677 ... read »
Feb 3, 2012 at 2:28 PM
Changing The Execution Context Of Your Self-Executing Function Blocks In JavaScript
@Michael, You definitely make a good point (and extra points for quoting movies - I love movies). When you use a return() statement to define the object's public API, it does provide a consistent a ... read »
Feb 3, 2012 at 2:04 PM
Changing The Execution Context Of Your Self-Executing Function Blocks In JavaScript
To quote Jurassic Park: "Just because you can doesn't mean you should". I completely, utterly disagree with the thought that this is more readable. Consider the current module pattern: if ... read »
Feb 3, 2012 at 1:10 PM
REST API Design Rulebook By Mark Masse
@Jordan, Yeah, WRML was created by Mark Masse (author of the book). I also found it to be a bit convoluted. I suppose it is intended to allow the Client to be able to programmaticaly respond to cha ... read »
Feb 3, 2012 at 1:08 PM
ColdFusion Supports HTTP Verbs PUT And DELETE (As Well As GET And POST)
@Jason, To be honest, I don't have good answers for that kinds of stuff. And, to the point, that is specifically why I *really* liked the REST API Design Rulebook by Mark Masse - he just cuts throu ... read »