Netscape browsers versions 1.1 and higher support a so-called ``cookie''
designed to help maintain state within a browser session. CGI.pm has
several methods that support cookies.
A cookie is a name=value pair much like the named parameters in a
CGI query string.
CGI scripts create one or more cookies and send them to the browser in the
HTTP header. The browser maintains a list of cookies that belong to a particular Web server, and returns them to the
CGI script during subsequent interactions.
In addition to the required name=value pair, each cookie has several
optional attributes:
- an expiration time
This is a time/date string (in a special
GMT format) that indicates when a cookie expires. The
cookie will be saved and returned to your script until this expiration date
is reached if the user exits Netscape and restarts it. If an expiration
date isn't specified, the cookie will remain active until the user quits
Netscape.
- a domain
This is a partial or complete domain name for which the cookie is valid.
The browser will return the cookie to any host that matches the partial
domain name. For example, if you specify a domain name of
``.capricorn.com'', then Netscape will return the cookie to Web servers
running on any of the machines ``www.capricorn.com'',
``www2.capricorn.com'', ``feckless.capricorn.com'', etc. Domain names must
contain at least two periods to prevent attempts to match on top level
domains like ``.edu''. If no domain is specified, then the browser will
only return the cookie to servers on the host the cookie originated from.
- a path
If you provide a cookie path attribute, the browser will check it against your script's
URL before returning the cookie. For example, if you specify the path ``/cgi-bin'', then the cookie will be returned to each of the scripts ``/cgi-bin/tally.pl'', ``/cgi-bin/order.pl'', and ``/cgi-bin/customer_service/complain.pl'', but not to the script ``/cgi-private/site_admin.pl''. By default, path is set to ``/'', which causes the cookie to be sent to any
CGI script on your site.
- a "secure" flag
If the ``secure'' attribute is set, the cookie will only be sent to your script if the
CGI request is occurring on a secure channel, such as
SSL.
The interface to Netscape cookies is the cookie() method:
$cookie = $query->cookie(-name=>'sessionID',
-value=>'xyzzy',
-expires=>'+1h',
-path=>'/cgi-bin/database',
-domain=>'.capricorn.org',
-secure=>1);
print $query->header(-cookie=>$cookie);
cookie() creates a new cookie. Its parameters include:
- -name
-
The name of the cookie (required). This can be any string at all. Although
Netscape limits its cookie names to non-whitespace alphanumeric characters,
CGI.pm removes this restriction by escaping and unescaping cookies behind
the scenes.
- -value
-
The value of the cookie. This can be any scalar value, array reference, or
even associative array reference. For example, you can store an entire
associative array into a cookie this way:
$cookie=$query->cookie(-name=>'family information',
-value=>\%childrens_ages);
- -path
-
The optional partial path for which this cookie will be valid, as described
above.
- -domain
-
The optional partial domain for which this cookie will be valid, as
described above.
- -expires
-
The optional expiration date for this cookie. The format is as described in
the section on the header() method:
"+1h" one hour from now
- -secure
-
If set to true, this cookie will only be used within a secure
SSL session.
The cookie created by cookie
must be incorporated into the
HTTP header within the string returned by the
header
method:
print $query->header(-cookie=>$my_cookie);
To create multiple cookies, give header
an array reference:
$cookie1 = $query->cookie(-name=>'riddle_name',
-value=>"The Sphynx's Question");
$cookie2 = $query->cookie(-name=>'answers',
-value=>\%answers);
print $query->header(-cookie=>[$cookie1,$cookie2]);
To retrieve a cookie, request it by name by calling cookie
method without the -value parameter:
use CGI;
$query = new CGI;
%answers = $query->cookie(-name=>'answers');
# $query->cookie('answers') will work too!
The cookie and
CGI namespaces are separate. If you have a parameter named 'answers' and a cookie named 'answers', the values retrieved by param
and cookie
are independent of each other. However, it's simple to turn a
CGI parameter into a cookie, and vice-versa:
# turn a CGI parameter into a cookie
$c=$q->cookie(-name=>'answers',-value=>[$q->param('answers')]);
# vice-versa
$q->param(-name=>'answers',-value=>[$q->cookie('answers')]);
See the cookie.cgi example script for some ideas on how to use cookies effectively.
NOTE: There appear to be some (undocumented) restrictions on Netscape cookies. In Netscape 2.01, at least,
I haven't been able to set more than three cookies at a time. There may also be limits on the length of cookies. If you need to store a lot of information, it's probably better to create a unique session
ID, store it in a cookie, and use the session
ID to locate an external file/database saved on the server's side of the connection.