Puting a State info a Stateless Browser
by Mark Grennan
Few Internet development concepts are as misunderstood as the HTTP cookie. I can't remember all the bizarre ideas I've heard. But the do work.
If you are developing an Internet application you soon find out you have no idea who is connecting to your application.
One way to identify someone is to give them a badge of your own. You may not know their name but you do know they are badge # 1234.
Almost every browser has a way for you to attach your badge to it. These badges are called COOKIES.
A cookie lets you pass a small pieces of information be stored on the client computer in a reasonably secure manner.
A common application of the cookie is storing the username and password you enter into a password-protected World Wide Web site. The first time you enter this information into a CGI-governed form, the CGI program has browser write the information back to a cookie on your hard disk. Rather than bothering you to enter the username and password the next time you enter the site, the server looks into the cookie data stored for that particular server and extracts the username and password for automatic validation processing behind the scenes.
Cookies have these "fields":
Notice that cookies are domain-specific. If one domain creates a cookie, another cannot access it through browser's cookie mechanism behind your back. That's why it's generally safe to store what I call "throwaway passwords" (those username/password pairs required for access to some free registration-required sites) in cookies. Moreover, sites that store passwords in a cookie usually do so as an encrypted string, making it more difficult for someone to highjack the cookie file from your PC while left unattended and figure out what your personal password scheme might be.
Not all cookies have to last beyond the current session, however. In fact, it is quite typical for cookies to be used only temporarily while working your way through a Web site. Many shopping sites employ one or more temporary cookie records to behave as the shopping cart to record items you intend to purchase. These items are copied to the order form at check-out time. But once the order form is submitted to the server, that client-side data is of no particular value. As it turns out, by not specifying an expiration date, browser keeps the cookie fresh in memory without writing it to the cookie file. When you quit browser, that cookie data disappears as expected.
To write cookie data to the cookie file, you use a simple JavaScript assignment operator with the document.cookie property. But the formatting of the data is crucial to achieving success. Here is the overall syntax for assigning a value to a cookie (optional items are in brackets):
document.cookie = "cookieName=cookieData
[; expires=timeInGMTString]
[; path=pathName]
[; domain=domainName]
[; secure]"
Let's examine each of the properties individually.
Each cookie must have a name and a string value (even if that value is an empty string). Such name-value pairs are fairly common in HTML, but they look odd in an assignment statement. For example, if you wanted to save the string "Mark" to a cookie named "userName", the JavaScript statement would be:
document.cookie = "userName=Mark"
If browser sees no existing cookie in the current domain/path with this name, then it automatically creates the cookie entry for you (although it won't necessarily write it to the cookie file right away); if the named cookie already exists, then browser replaces the old data with the new. Retrieving document.cookie at this point would yield the string
userName=Mark
You can omit all the other cookie-setting properties, in which case browser uses default values, as explained below. For temporary cookies (i.e., those that don't have to persist beyond the current browser session), the name/data pair is usually all you need.
The entire name/data element must be a single string with no semi-colons, commas, or character spaces. To take care of spaces between words, preprocess the data with the JavaScript escape() function, which ASCII encodes the spaces as %20 (and then be sure to unescape() the data to restore the human-readable spaces when you retrieve the cookie later).
If you add extra parameters, notice that they are all included in the single string that is assigned to the document.cookie property. Also, each of the parameters must be separated by a semi-colon and space.
Expiration dates, when supplied, must be passed as GMT strings. To calculate an expiration date based on today's date, use JavaScript's Date object as follows:
var exp = new Date() var oneYearFromNow = exp.getTime() + (365 * 24 * 60 * 60 * 1000) exp.setTime(oneYearFromNow)
Then convert the date to accepted GMT string format:
document.cookie = "userName=Mark; expires=" + exp.toGMTString()
In the cookie file, the expiration date and time is stored as a numeric value (seconds), but to set it, you need to supply the time in GMT format. You can delete a cookie before it expires by setting the named cookie's expiration date to a time and date earlier than the current time and date.
If you don't set the expiration date the cookie is only a temporary one. It will never be written to the cookie file, and will be forgotten the next time you quit browser.
For client-side cookies, the default path setting (automatically entered as "/" for the current directory when no value is passed along) is usually the best choice. It is possible, of course, to create a duplicate copy of a cookie with a separate path (and domain) so that the same data is available to a document located in another area of your site (or the Web).
To help synchronize cookie data with a particular document (or group of documents), browser matches the domain of the current document with the domain values of cookie entries in the cookie file. Therefore, if you were to display a list of all cookie data contained in a document.cookie property, you would get back all the name/data cookie pairs from the cookie file whose domain and path parameters match those of the current document.
If you don't set the domain, the default will be the name of the server given in the URL. This make the brower only hack up the cookie if the request is comming from the same server. Be aware that a domain setting must have at least two periods, such as:
.slashdot.net
.hotwired.com
If you omit the secure parameter, then it is assumed that the cookie data is accessible to any document or CGI program that meets the other domain and path matching properties. For client-side scripting of cookies, you should omit this parameter when saving a cookie.
Cookie data retrieved is contained in one string, including the whole name/data pair. Even though other parameters for each cookie are stored in the cookie file, only the name/data pairs can be retrieved via JavaScript. Moreover, when two or more (up to a maximum of 20) cookies meet the current domain/path criteria, these are also lumped into that string, delimited by a semi-colon and space. For example, a document.cookie string might look like this:
userName=Fred; password=NikL2sPacU
In other words, you can't treat named cookies as objects. Instead, you must parse the entire cookie string, extracting the data from the desired name/data pair.
When you know that you are dealing with only one cookie (and no more will ever be added to the domain/path combination), you can customize the extraction based on known data, such as the cookie name. For example with a cookie name that is seven characters long, you could extract the data with a statement like this:
var data = unescape(document.cookie.substring(7,document.cookie.length))
with the first parameter of the substring() method including the equals sign separating the name from the data.
A better approach is to create a general purpose function that can work with single or multiple entry cookies. Here is one I use in some of my pages:
function getCookieData(label) {
var labelLen = label.length
var cLen = document.cookie.length
var i = 0
while (i
Calls to this function pass the name of the desired cookie as a parameter. The function parses the entire cookie string, chipping away any mismatched entries (through the semi-colons) until it finds the cookie name.