1CGI::Session(3) User Contributed Perl Documentation CGI::Session(3)
2
3
4
6 CGI::Session - persistent session data in CGI applications
7
9 # Object initialization:
10 use CGI::Session;
11 $session = CGI::Session->new();
12
13 $CGISESSID = $session->id();
14
15 # Send proper HTTP header with cookies:
16 print $session->header();
17
18 # Storing data in the session:
19 $session->param('f_name', 'Sherzod');
20 # or
21 $session->param(-name=>'l_name', -value=>'Ruzmetov');
22
23 # Flush the data from memory to the storage driver at least before your
24 # program finishes since auto-flushing can be unreliable.
25 $session->flush();
26
27 # Retrieving data:
28 my $f_name = $session->param('f_name');
29 # or
30 my $l_name = $session->param(-name=>'l_name');
31
32 # Clearing a certain session parameter:
33 $session->clear(["l_name", "f_name"]);
34
35 # Expire '_is_logged_in' flag after 10 idle minutes:
36 $session->expire('is_logged_in', '+10m')
37
38 # Expire the session itself after 1 idle hour:
39 $session->expire('+1h');
40
41 # Delete the session for good:
42 $session->delete();
43 $session->flush(); # Recommended practice says use flush() after delete().
44
46 CGI::Session provides an easy, reliable and modular session management
47 system across HTTP requests.
48
50 Following is the overview of all the available methods accessible via
51 CGI::Session object.
52
53 new()
54 new( $sid )
55 new( $query )
56 new( $dsn, $query||$sid )
57 new( $dsn, $query||$sid, \%dsn_args )
58 new( $dsn, $query||$sid, \%dsn_args, \%session_params )
59 Constructor. Returns new session object, or undef on failure. Error
60 message is accessible through errstr() - class method. If called on an
61 already initialized session will re-initialize the session based on
62 already configured object. This is only useful after a call to load().
63
64 Can accept up to three arguments, $dsn - Data Source Name, $query||$sid
65 - query object OR a string representing session id, and finally,
66 \%dsn_args, arguments used by $dsn components.
67
68 If called without any arguments, $dsn defaults to
69 driver:file;serializer:default;id:md5, $query||$sid defaults to
70 "CGI->new()", and "\%dsn_args" defaults to undef.
71
72 If called with a single argument, it will be treated either as $query
73 object, or $sid, depending on its type. If argument is a string , new()
74 will treat it as session id and will attempt to retrieve the session
75 from data store. If it fails, will create a new session id, which will
76 be accessible through id() method. If argument is an object, cookie()
77 and param() methods will be called on that object to recover a
78 potential $sid and retrieve it from data store. If it fails, new() will
79 create a new session id, which will be accessible through id() method.
80 name() will define the name of the query parameter and/or cookie name
81 to be requested, defaults to CGISESSID.
82
83 If called with two arguments first will be treated as $dsn, and second
84 will be treated as $query or $sid or undef, depending on its type. Some
85 examples of this syntax are:
86
87 $s = CGI::Session->new("driver:mysql", undef);
88 $s = CGI::Session->new("driver:sqlite", $sid);
89 $s = CGI::Session->new("driver:db_file", $query);
90 $s = CGI::Session->new("serializer:storable;id:incr", $sid);
91 # etc...
92
93 Briefly, new() will return an initialized session object with a valid
94 id, whereas load() may return an empty session object with an undefined
95 id.
96
97 Tests are provided (t/new_with_undef.t and t/load_with_undef.t) to
98 clarify the result of calling new() and load() with undef, or with an
99 initialized CGI object with an undefined or fake CGISESSID.
100
101 You are strongly advised to run the old-fashioned 'make test
102 TEST_FILES=t/new_with_undef.t TEST_VERBOSE=1' or the new-fangled 'prove
103 -v t/new_with_undef.t', for both new*.t and load*.t, and examine the
104 output.
105
106 Following data source components are supported:
107
108 • driver - CGI::Session driver. Available drivers are file, db_file,
109 mysql and sqlite. Third party drivers are welcome. For driver specs
110 consider CGI::Session::Driver
111
112 • serializer - serializer to be used to encode the data structure
113 before saving in the disk. Available serializers are storable,
114 freezethaw and default. Default serializer will use Data::Dumper.
115
116 • id - ID generator to use when new session is to be created.
117 Available ID generator is md5
118
119 For example, to get CGI::Session store its data using DB_File and
120 serialize data using FreezeThaw:
121
122 $s = CGI::Session->new("driver:DB_File;serializer:FreezeThaw", undef);
123
124 If called with three arguments, first two will be treated as in the
125 previous example, and third argument will be "\%dsn_args", which will
126 be passed to $dsn components (namely, driver, serializer and id
127 generators) for initialization purposes. Since all the $dsn components
128 must initialize to some default value, this third argument should not
129 be required for most drivers to operate properly.
130
131 If called with four arguments, the first three match previous examples.
132 The fourth argument must be a hash reference with parameters to be used
133 by the CGI::Session object. (see \%session_params above )
134
135 The following is a list of the current keys:
136
137 • name - Name to use for the cookie/query parameter name. This
138 defaults to CGISESSID. This can be altered or accessed by the
139 "name" accessor.
140
141 undef is acceptable as a valid placeholder to any of the above
142 arguments, which will force default behavior.
143
144 load()
145 load( $query||$sid )
146 load( $dsn, $query||$sid )
147 load( $dsn, $query, \%dsn_args )
148 load( $dsn, $query, \%dsn_args, \%session_params )
149 Accepts the same arguments as new(), and also returns a new session
150 object, or undef on failure. The difference is, new() can create a new
151 session if it detects expired and non-existing sessions, but load()
152 does not.
153
154 load() is useful to detect expired or non-existing sessions without
155 forcing the library to create new sessions. So now you can do something
156 like this:
157
158 $s = CGI::Session->load() or die CGI::Session->errstr();
159 if ( $s->is_expired ) {
160 print $s->header(),
161 $cgi->start_html(),
162 $cgi->p("Your session timed out! Refresh the screen to start new session!")
163 $cgi->end_html();
164 exit(0);
165 }
166
167 if ( $s->is_empty ) {
168 $s = $s->new() or die $s->errstr;
169 }
170
171 Notice: All expired sessions are empty, but not all empty sessions are
172 expired!
173
174 Briefly, new() will return an initialized session object with a valid
175 id, whereas load() may return an empty session object with an undefined
176 id.
177
178 Tests are provided (t/new_with_undef.t and t/load_with_undef.t) to
179 clarify the result of calling new() and load() with undef, or with an
180 initialized CGI object with an undefined or fake CGISESSID.
181
182 You are strongly advised to run the old-fashioned 'make test
183 TEST_FILES=t/new_with_undef.t TEST_VERBOSE=1' or the new-fangled 'prove
184 -v t/new_with_undef.t', for both new*.t and load*.t, and examine the
185 output.
186
187 id()
188 Returns effective ID for a session. Since effective ID and claimed ID
189 can differ, valid session id should always be retrieved using this
190 method.
191
192 param($name)
193 param(-name=>$name)
194 Used in either of the above syntax returns a session parameter set to
195 $name or undef if it doesn't exist. If it's called on a deleted method
196 param() will issue a warning but return value is not defined.
197
198 param($name, $value)
199 param(-name=>$name, -value=>$value)
200 Used in either of the above syntax assigns a new value to $name
201 parameter, which can later be retrieved with previously introduced
202 param() syntax. $value may be a scalar, arrayref or hashref.
203
204 Attempts to set parameter names that start with _SESSION_ will trigger
205 a warning and undef will be returned.
206
207 param_hashref()
208 Deprecated. Use dataref() instead.
209
210 dataref()
211 Returns reference to session's data table:
212
213 $params = $s->dataref();
214 $sid = $params->{_SESSION_ID};
215 $name= $params->{name};
216 # etc...
217
218 Useful for having all session data in a hashref, but too risky to
219 update.
220
221 save_param()
222 save_param($query)
223 save_param($query, \@list)
224 Saves query parameters to session object. In other words, it's the same
225 as calling param($name, $value) for every single query parameter
226 returned by "$query->param()". The first argument, if present, should
227 be either CGI object or any object which can provide param() method. If
228 it's undef, defaults to the return value of query(), which returns
229 "CGI->new". If second argument is present and is a reference to an
230 array, only those query parameters found in the array will be stored in
231 the session. undef is a valid placeholder for any argument to force
232 default behavior.
233
234 load_param()
235 load_param($query)
236 load_param($query, \@list)
237 Loads session parameters into a query object. The first argument, if
238 present, should be query object, or any other object which can provide
239 param() method. If second argument is present and is a reference to an
240 array, only parameters found in that array will be loaded to the query
241 object.
242
243 clear()
244 clear('field')
245 clear(\@list)
246 Clears parameters from the session object.
247
248 With no parameters, all fields are cleared. If passed a single
249 parameter or a reference to an array, only the named parameters are
250 cleared.
251
252 flush()
253 Synchronizes data in memory with the copy serialized by the driver.
254 Call flush() if you need to access the session from outside the current
255 session object. You should call flush() sometime before your program
256 exits.
257
258 As a last resort, CGI::Session will automatically call flush for you
259 just before the program terminates or session object goes out of scope.
260 Automatic flushing has proven to be unreliable, and in some cases is
261 now required in places that worked with CGI::Session 3.x.
262
263 Always explicitly calling flush() on the session before the program
264 exits is recommended. For extra safety, call it immediately after every
265 important session update.
266
267 Also see "A Warning about Auto-flushing"
268
269 atime()
270 Read-only method. Returns the last access time of the session in
271 seconds from epoch. This time is used internally while auto-expiring
272 sessions and/or session parameters.
273
274 ctime()
275 Read-only method. Returns the time when the session was first created
276 in seconds from epoch.
277
278 expire()
279 expire($time)
280 expire($param, $time)
281 Sets expiration interval relative to atime().
282
283 If used with no arguments, returns the expiration interval if it was
284 ever set. If no expiration was ever set, returns undef. For backwards
285 compatibility, a method named etime() does the same thing.
286
287 Second form sets an expiration time. This value is checked when
288 previously stored session is asked to be retrieved, and if its
289 expiration interval has passed, it will be expunged from the disk
290 immediately. Passing 0 cancels expiration.
291
292 By using the third syntax you can set the expiration interval for a
293 particular session parameter, say ~logged-in. This would cause the
294 library call clear() on the parameter when its time is up. Note it only
295 makes sense to set this value to something earlier than when the whole
296 session expires. Passing 0 cancels expiration.
297
298 All the time values should be given in the form of seconds. Following
299 keywords are also supported for your convenience:
300
301 +-----------+---------------+
302 | alias | meaning |
303 +-----------+---------------+
304 | s | Second |
305 | m | Minute |
306 | h | Hour |
307 | d | Day |
308 | w | Week |
309 | M | Month |
310 | y | Year |
311 +-----------+---------------+
312
313 Examples:
314
315 $session->expire("2h"); # expires in two hours
316 $session->expire(0); # cancel expiration
317 $session->expire("~logged-in", "10m"); # expires '~logged-in' parameter after 10 idle minutes
318
319 Note: all the expiration times are relative to session's last access
320 time, not to its creation time. To expire a session immediately, call
321 delete(). To expire a specific session parameter immediately, call
322 clear([$name]).
323
324 is_new()
325 Returns true only for a brand new session.
326
327 is_expired()
328 Tests whether session initialized using load() is to be expired. This
329 method works only on sessions initialized with load():
330
331 $s = CGI::Session->load() or die CGI::Session->errstr;
332 if ( $s->is_expired ) {
333 die "Your session expired. Please refresh";
334 }
335 if ( $s->is_empty ) {
336 $s = $s->new() or die $s->errstr;
337 }
338
339 is_empty()
340 Returns true for sessions that are empty. It's preferred way of testing
341 whether requested session was loaded successfully or not:
342
343 $s = CGI::Session->load($sid);
344 if ( $s->is_empty ) {
345 $s = $s->new();
346 }
347
348 Actually, the above code is nothing but waste. The same effect could've
349 been achieved by saying:
350
351 $s = CGI::Session->new( $sid );
352
353 is_empty() is useful only if you wanted to catch requests for expired
354 sessions, and create new session afterwards. See is_expired() for an
355 example.
356
357 ip_match()
358 Returns true if $ENV{REMOTE_ADDR} matches the remote address stored in
359 the session.
360
361 If you have an application where you are sure your users' IPs are
362 constant during a session, you can consider enabling an option to make
363 this check:
364
365 use CGI::Session '-ip_match';
366
367 Usually you don't call ip_match() directly, but by using the above
368 method. It is useful only if you want to call it inside of coderef
369 passed to the find() method.
370
371 delete()
372 Sets the objects status to be "deleted". Subsequent read/write
373 requests on the same object will fail. To physically delete it from
374 the data store you need to call flush(). CGI::Session attempts to do
375 this automatically when the object is being destroyed (usually as the
376 script exits), but see "A Warning about Auto-flushing".
377
378 find( \&code )
379 find( $dsn, \&code )
380 find( $dsn, \&code, \%dsn_args )
381 Experimental feature. Executes \&code for every session object stored
382 in disk, passing initialized CGI::Session object as the first argument
383 of \&code. Useful for housekeeping purposes, such as for removing
384 expired sessions. Following line, for instance, will remove sessions
385 already expired, but are still in disk:
386
387 The following line, for instance, will remove sessions already expired,
388 but which are still on disk:
389
390 CGI::Session->find( sub {} );
391
392 Notice, above \&code didn't have to do anything, because load(), which
393 is called to initialize sessions inside find(), will automatically
394 remove expired sessions. Following example will remove all the objects
395 that are 10+ days old:
396
397 CGI::Session->find( \&purge );
398 sub purge {
399 my ($session) = @_;
400 next if $session->is_empty; # <-- already expired?!
401 if ( ($session->ctime + 3600*240) <= time() ) {
402 $session->delete();
403 $session->flush(); # Recommended practice says use flush() after delete().
404 }
405 }
406
407 Note: find will not change the modification or access times on the
408 sessions it returns.
409
410 Explanation of the 3 parameters to find():
411
412 $dsn
413 This is the DSN (Data Source Name) used by CGI::Session to control
414 what type of sessions you previously created and what type of
415 sessions you now wish method find() to pass to your callback.
416
417 The default value is defined above, in the docs for method new(),
418 and is 'driver:file;serializer:default;id:md5'.
419
420 Do not confuse this DSN with the DSN arguments mentioned just
421 below, under \%dsn_args.
422
423 \&code
424 This is the callback provided by you (i.e. the caller of method
425 find()) which is called by CGI::Session once for each session found
426 by method find() which matches the given $dsn.
427
428 There is no default value for this coderef.
429
430 When your callback is actually called, the only parameter is a
431 session. If you want to call a subroutine you already have with
432 more parameters, you can achieve this by creating an anonymous
433 subroutine that calls your subroutine with the parameters you want.
434 For example:
435
436 CGI::Session->find($dsn, sub { my_subroutine( @_, 'param 1', 'param 2' ) } );
437 CGI::Session->find($dsn, sub { $coderef->( @_, $extra_arg ) } );
438
439 Or if you wish, you can define a sub generator as such:
440
441 sub coderef_with_args {
442 my ( $coderef, @params ) = @_;
443 return sub { $coderef->( @_, @params ) };
444 }
445
446 CGI::Session->find($dsn, coderef_with_args( $coderef, 'param 1', 'param 2' ) );
447
448 \%dsn_args
449 If your $dsn uses file-based storage, then this hashref might
450 contain keys such as:
451
452 {
453 Directory => Value 1,
454 NoFlock => Value 2,
455 UMask => Value 3
456 }
457
458 If your $dsn uses db-based storage, then this hashref contains (up
459 to) 3 keys, and looks like:
460
461 {
462 DataSource => Value 1,
463 User => Value 2,
464 Password => Value 3
465 }
466
467 These 3 form the DSN, username and password used by DBI to control
468 access to your database server, and hence are only relevant when
469 using db-based sessions.
470
471 The default value of this hashref is undef.
472
473 Note: find() is meant to be convenient, not necessarily efficient. It's
474 best suited in cron scripts.
475
476 name($new_name)
477 The $new_name parameter is optional. If supplied it sets the query or
478 cookie parameter name to be used.
479
480 It defaults to $CGI::Session::NAME, which defaults to CGISESSID.
481
482 You are strongly discouraged from using the global variable
483 $CGI::Session::NAME, since it is deprecated (as are all global
484 variables) and will be removed in a future version of this module.
485
486 Return value: The current query or cookie parameter name.
487
489 remote_addr()
490 Returns the remote address of the user who created the session for the
491 first time. Returns undef if variable REMOTE_ADDR wasn't present in the
492 environment when the session was created.
493
494 errstr()
495 Class method. Returns last error message from the library.
496
497 dump()
498 Returns a dump of the session object. Useful for debugging purposes
499 only.
500
501 header()
502 A wrapper for "CGI"'s header() method. Calling this method is
503 equivalent to something like this:
504
505 $cookie = CGI::Cookie->new(-name=>$session->name, -value=>$session->id);
506 print $cgi->header(-cookie=>$cookie, @_);
507
508 You can minimize the above into:
509
510 print $session->header();
511
512 It will retrieve the name of the session cookie from "$session-"name()>
513 which defaults to $CGI::Session::NAME. If you want to use a different
514 name for your session cookie, do something like this before creating
515 session object:
516
517 CGI::Session->name("MY_SID");
518 $session = CGI::Session->new(undef, $cgi, \%attrs);
519
520 Now, $session->header() uses "MY_SID" as the name for the session
521 cookie. For all additional options that can be passed, see the header()
522 docs in "CGI".
523
524 query()
525 Returns query object associated with current session object. Default
526 query object class is "CGI".
527
528 DEPRECATED METHODS
529 These methods exist solely for for compatibility with CGI::Session 3.x.
530
531 close()
532
533 Closes the session. Using flush() is recommended instead, since that's
534 exactly what a call to close() does now.
535
537 CGI::Session consists of several components such as drivers,
538 serializers and id generators. This section lists what is available.
539
540 DRIVERS
541 The following drivers are included in the standard distribution:
542
543 • file - default driver for storing session data in plain files. Full
544 name: CGI::Session::Driver::file
545
546 • db_file - for storing session data in BerkelyDB. Requires: DB_File.
547 Full name: CGI::Session::Driver::db_file
548
549 • mysql - for storing session data in MySQL tables. Requires DBI and
550 DBD::mysql. Full name: CGI::Session::Driver::mysql
551
552 • sqlite - for storing session data in SQLite. Requires DBI and
553 DBD::SQLite. Full name: CGI::Session::Driver::sqlite
554
555 Other drivers are available from CPAN.
556
557 SERIALIZERS
558 • default - default data serializer. Uses standard Data::Dumper.
559 Full name: CGI::Session::Serialize::default.
560
561 • storable - serializes data using Storable. Requires Storable. Full
562 name: CGI::Session::Serialize::storable.
563
564 • freezethaw - serializes data using FreezeThaw. Requires FreezeThaw.
565 Full name: CGI::Session::Serialize::freezethaw
566
567 • yaml - serializes data using YAML. Requires YAML or YAML::Syck.
568 Full name: CGI::Session::Serialize::yaml
569
570 ID GENERATORS
571 The following ID generators are included in the standard distribution.
572
573 • md5 - generates 32 character long hexadecimal string. Requires
574 Digest::MD5. Full name: CGI::Session::ID::md5.
575
576 • incr - generates incremental session ids.
577
578 • static - generates static session ids. CGI::Session::ID::static
579
581 Auto-flushing can be unreliable for the following reasons. Explicit
582 flushing after key session updates is recommended.
583
584 If the "DBI" handle goes out of scope before the session variable
585 For database-stored sessions, if the "DBI" handle has gone out of
586 scope before the auto-flushing happens, auto-flushing will fail.
587
588 Circular references
589 If the calling code contains a circular reference, it's possible
590 that your "CGI::Session" object will not be destroyed until it is
591 too late for auto-flushing to work. You can find circular
592 references with a tool like Devel::Cycle.
593
594 In particular, these modules are known to contain circular
595 references which lead to this problem:
596
597 CGI::Application::Plugin::DebugScreen V 0.06
598 CGI::Application::Plugin::ErrorPage before version 1.20
599 Signal handlers
600 If your application may receive signals, there is an increased
601 chance that the signal will arrive after the session was updated
602 but before it is auto-flushed at object destruction time.
603
605 You are strongly encouraged to refer to, at least, the first of these
606 articles, for help with UTF8.
607
608 <http://en.wikibooks.org/wiki/Perl_Programming/Unicode_UTF-8>
609
610 <http://perl.bristolbath.org/blog/lyle/2008/12/giving-cgiapplication-internationalization-i18n.html>
611
612 <http://metsankulma.homelinux.net/cgi-bin/l10n_example_4/main.cgi>
613
614 <http://rassie.org/archives/247>
615
616 <http://www.di-mgt.com.au/cryptoInternational2.html>
617
618 Briefly, these are the issues:
619
620 The file containing the source code of your program
621 Consider "use utf8;" or "use encoding 'utf8';".
622
623 Influencing the encoding of the program's input
624 Use:
625
626 binmode STDIN, ":encoding(utf8)";.
627
628 Of course, the program can get input from other sources, e.g. HTML template files, not just STDIN.
629
630 Influencing the encoding of the program's output
631 Use:
632
633 binmode STDOUT, ":encoding(utf8)";
634
635 When using CGI.pm, you can use $q->charset('UTF-8'). This is the same as passing 'UTF-8' to CGI's C<header()> method.
636
637 Alternately, when using CGI::Session, you can use $session->header(charset => 'utf-8'), which will be
638 passed to the query object's C<header()> method. Clearly this is preferable when the query object might not be
639 of type CGI.
640
641 See L</header()> for a fuller discussion of the use of the C<header()> method in conjunction with cookies.
642
644 This document is also available in Japanese.
645
646 o Translation based on 4.14:
647 http://digit.que.ne.jp/work/index.cgi?Perldoc/ja
648
649 o Translation based on 3.11, including Cookbook and Tutorial:
650 http://perldoc.jp/docs/modules/CGI-Session-3.11/
651
653 CGI::Session evolved to what it is today with the help of following
654 developers. The list doesn't follow any strict order, but somewhat
655 chronological. Specifics can be found in Changes file
656
657 Andy Lester
658 Brian King <mrbbking@mac.com>
659 Olivier Dragon <dragon@shadnet.shad.ca>
660 Adam Jacob <adam@sysadminsith.org>
661 Igor Plisco <igor@plisco.ru>
662 Mark Stosberg
663 Matt LeBlanc <mleblanc@cpan.org>
664 Shawn Sorichetti
665 Ron Savage
666 Rhesa Rozendaal
667 He suggested Devel::Cycle to help debugging.
668
669 Also, many people on the CGI::Application and CGI::Session mailing
670 lists have contributed ideas and suggestions, and battled publicly with
671 bugs, all of which has helped.
672
674 Copyright (C) 2001-2005 Sherzod Ruzmetov <sherzodr@cpan.org>. All
675 rights reserved. This library is free software. You can modify and or
676 distribute it under the same terms as Perl itself.
677
679 You can see what the developers have been up to since the last release
680 by checking out the code repository. You can browse the git repository
681 from here:
682
683 http://github.com/cromedome/cgi-session/tree/master
684
685 Or check out the code with:
686
687 git clone git://github.com/cromedome/cgi-session.git
688
690 If you need help using CGI::Session, ask on the mailing list. You can
691 ask the list by sending your questions to
692 cgi-session-user@lists.sourceforge.net .
693
694 You can subscribe to the mailing list at
695 https://lists.sourceforge.net/lists/listinfo/cgi-session-user .
696
697 Bug reports can be submitted at
698 http://rt.cpan.org/NoAuth/ReportBug.html?Queue=CGI-Session
699
701 Sherzod Ruzmetov "sherzodr@cpan.org"
702
703 Mark Stosberg became a co-maintainer during the development of 4.0.
704 "markstos@cpan.org".
705
706 Ron Savage became a co-maintainer during the development of 4.30.
707 "rsavage@cpan.org".
708
709 If you would like support, ask on the mailing list as describe above.
710 The maintainers and other users are subscribed to it.
711
713 To learn more both about the philosophy and CGI::Session programming
714 style, consider the following:
715
716 • CGI::Session::Tutorial - extended CGI::Session manual. Also
717 includes library architecture and driver specifications.
718
719 • We also provide mailing lists for CGI::Session users. To subscribe
720 to the list or browse the archives visit
721 https://lists.sourceforge.net/lists/listinfo/cgi-session-user
722
723 • RFC 2109 - The primary spec for cookie handing in use, defining the
724 "Cookie:" and "Set-Cookie:" HTTP headers. Available at
725 <http://www.ietf.org/rfc/rfc2109.txt>. A newer spec, RFC 2965 is
726 meant to obsolete it with "Set-Cookie2" and "Cookie2" headers, but
727 even of 2008, the newer spec is not widely supported. See
728 <http://www.ietf.org/rfc/rfc2965.txt>
729
730 • Apache::Session - an alternative to CGI::Session.
731
732
733
734perl v5.38.0 2023-07-20 CGI::Session(3)