Monday, May 18, 2009
You're Gonna Lose That Cookie
Blog Entry #145
We continue today with our analysis of HTML Goodies' "So, You Want To Set A Cookie, Huh?" tutorial. In the "Fetch" section of the previous entry, we mounted on a slide and placed under the microscope the tutorial's demo page, which with Internet Explorer (specifically, MSIE 5.2.3 for Mac OS X) works as advertised, more or less, correctly returning the user's cookie value for display on the page's first line. But what about other browsers, huh? After setting a dataCookie=oatmeal raisin cookie with the putCookie( ) function, the demo page display when using Firefox, Opera, or Safari (again excluding the <<...Back link) is
You Entered No cookie name found.dataCookie.
No cookie matching was found
if the text box value remains unquoted - not what we want, needless to say.
When I visit the "So, You Want To Set A Cookie, Huh?" page with the above non-MSIE browsers, HTML Goodies writes five cookies to my hard disk; the demo page detects these cookies: the if (document.cookie) condition in the getName( ) function returns true. The demo page does not detect the dataCookie=oatmeal raisin cookie, however. Here are the code-level details:
• In the getName( ) function, document.cookie.indexOf(cookie_name) returns -1; with index = -1, getName( ) returns and assigns to YouWrote No cookie name found. + dataCookie (Test), which is written to the demo page's first line.
To refresh your memory, the getName( ) function as it appears in the demo page source is reproduced in the div below:
• In the testCookie( ) function, name (dataCookie) is not found in cookieString (document.cookie) in any of the while loop's iterations, and thus the Boolean cookieFound variable stays at its initial value, false; consequently, testCookie( ) returns and assigns to testcx No cookie matching was found, which is written to the demo page's second line.
So why does MSIE detect the dataCookie=oatmeal raisin cookie but the other browsers don't? Let's go back and take a closer look at the putCookie( ) statement that writes the cookie:
document.cookie = cookie_name + "=" + YouEntered
+ "; expires=Monday, 04-Apr-2010 05:00:00 GMT";
The above command sets a name value, a value value, and an expires value for the cookie, but it doesn't set a domain value or a path value; in contrast, the great majority of cookie-setting Web sites set both domain and path values for their cookies. Here is the $64,000 question: Although the domain and path attributes are in fact optional when writing a cookie, what happens if we don't specify values for these attributes?
If you do not specify a value for [the domain attribute], Navigator uses the host name of the server which generated the cookie response.
If you do not specify a value for [the path attribute], Navigator uses the path of the document that created the cookie property.
More formally, the W3C also weighs in on this issue in its cookie attribute entry in the DOM Level 2 HTML Specification:
If no domain attribute is specified, then the domain attribute for the new value defaults to the host portion of an absolute URI [IETF RFC 2396] of the current frame or document. If no path attribute is specified, then the path attribute for the new value defaults to the absolute path portion of the URI [IETF RFC 2396] of the current frame or document.
To look at it another way, if the domain and path attributes for a cookie are not set, they (are supposed to) default to values that limit the generality of the cookie - I leave it to others to decide if this is as it should be, or not.
(The above screen shot was taken when using Safari. Note that the domain and path attributes for the other HTML Goodies cookies have been given the most general settings possible - .htmlgoodies.com and /, respectively - so that these cookies will be 'recognized' by every page at the HTML Goodies site.)
And how does MSIE handle a cookie's domain and path attributes? The MSDN Library's cookie property page tells you what happens when these attributes are set but, significantly, is silent on what happens when these attributes are not set; fortunately, this information can again be fished out of the browser Preferences... pane, which reveals that for the dataCookie=oatmeal raisin cookie,
(a) not setting the domain attribute causes domain to default to www.htmlgoodies.com - so far, so normal - but
(b) not setting the path attribute causes path to default to the more-general-than-it-should-be /:
The dataCookie=oatmeal raisin cookie now passes both domain matching and path matching and is therefore sent to the www.htmlgoodies.com server when the demo page is requested, and that's why you see the oatmeal raisin value on the demo page when using MSIE.
The "So, You Want To Set A Cookie, Huh?" tutorial dates to a former 'incarnation' of HTML Goodies, in which the tutorial and demo page URL paths were likely identical and if so Joe could get away with not specifying a path attribute for the dataCookie cookie. As for the present incarnation of HTML Goodies, you have probably figured out that the tutorial demo's browser-specific behavior can be resolved by adding a path=/ parameter to the putCookie( ) document.cookie-writing statement:
document.cookie = cookie_name + "=" + YouEntered
+ "; path=/; expires=Monday, 04-Apr-2010 05:00:00 GMT";
I have crafted my own little shopping cart cookie demo that illustrates some aspects of the tutorial's scripts. In the div below, select a fruit item and then click the Add to Cart button.
(Your browser must be set to accept 'third-party' cookies for the demo to work.)
Like Joe's demo, my demo writes a cookie and generates a cookie-related output based on the user's input; however, my demo differs from Joe's demo in two key respects:
(1) In the "Welcome, shopper" div, I limit the user to three input choices.
(2) The "Please confirm your order" div prints out not the cookie value itself but a longer text string corresponding to that value.
N.B. My demo cookie does not specify an expires attribute - the cookie will be gone when you quit your browser.