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('answers');
# $query->cookie(-name=>'answers') works too!
To retrieve the names of all cookies passed to your
script, call cookie() without any parameters. This allows
you to iterate through all cookies:
foreach $name ($query->cookie()) {
print $query->cookie($name);
}
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 is also limits on the length of cookies,
they can only be a maximum of 4 kb. 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.