source: trunk/gsdl/packages/w3mir/libwww-perl-5.36/t/base/cookies.t@ 719

Last change on this file since 719 was 719, checked in by davidb, 25 years ago

added w3mir package

  • Property svn:keywords set to Author Date Id Revision
File size: 15.3 KB
Line 
1print "1..32\n";
2
3#use LWP::Debug '+';
4
5use HTTP::Cookies;
6use HTTP::Request;
7use HTTP::Response;
8
9#-------------------------------------------------------------------
10# First we check that it works for the original example at
11# http://www.netscape.com/newsref/std/cookie_spec.html
12
13# Client requests a document, and receives in the response:
14#
15# Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/; expires=Wednesday, 09-Nov-99 23:12:40 GMT
16#
17# When client requests a URL in path "/" on this server, it sends:
18#
19# Cookie: CUSTOMER=WILE_E_COYOTE
20#
21# Client requests a document, and receives in the response:
22#
23# Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/
24#
25# When client requests a URL in path "/" on this server, it sends:
26#
27# Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001
28#
29# Client receives:
30#
31# Set-Cookie: SHIPPING=FEDEX; path=/fo
32#
33# When client requests a URL in path "/" on this server, it sends:
34#
35# Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001
36#
37# When client requests a URL in path "/foo" on this server, it sends:
38#
39# Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001; SHIPPING=FEDEX
40#
41# The last Cookie is buggy, because both specifications says that the
42# most specific cookie must be sent first. SHIPPING=FEDEX is the
43# most specific and should thus be first.
44
45$c = HTTP::Cookies->new;
46
47$req = HTTP::Request->new(GET => "http://www.acme.com/");
48
49$res = HTTP::Response->new(200, "OK");
50$res->request($req);
51$res->header("Set-Cookie" => "CUSTOMER=WILE_E_COYOTE; path=/; expires=Wednesday, 09-Nov-99 23:12:40 GMT");
52$c->extract_cookies($res);
53
54$req = HTTP::Request->new(GET => "http://www.acme.com/");
55$c->add_cookie_header($req);
56
57print "not " unless $req->header("Cookie") eq "CUSTOMER=WILE_E_COYOTE" &&
58 $req->header("Cookie2") eq "\$Version=1";
59print "ok 1\n";
60
61$res->request($req);
62$res->header("Set-Cookie" => "PART_NUMBER=ROCKET_LAUNCHER_0001; path=/");
63$c->extract_cookies($res);
64
65$req = HTTP::Request->new(GET => "http://www.acme.com/foo/bar");
66$c->add_cookie_header($req);
67
68$h = $req->header("Cookie");
69print "not " unless $h =~ /PART_NUMBER=ROCKET_LAUNCHER_0001/ &&
70 $h =~ /CUSTOMER=WILE_E_COYOTE/;
71print "ok 2\n";
72
73$res->request($req);
74$res->header("Set-Cookie", "SHIPPING=FEDEX; path=/foo");
75$c->extract_cookies($res);
76
77$req = HTTP::Request->new(GET => "http://www.acme.com/");
78$c->add_cookie_header($req);
79
80$h = $req->header("Cookie");
81print "not " unless $h =~ /PART_NUMBER=ROCKET_LAUNCHER_0001/ &&
82 $h =~ /CUSTOMER=WILE_E_COYOTE/ &&
83 $h !~ /SHIPPING=FEDEX/;
84print "ok 3\n";
85
86
87$req = HTTP::Request->new(GET => "http://www.acme.com/foo/");
88$c->add_cookie_header($req);
89
90$h = $req->header("Cookie");
91print "not " unless $h =~ /PART_NUMBER=ROCKET_LAUNCHER_0001/ &&
92 $h =~ /CUSTOMER=WILE_E_COYOTE/ &&
93 $h =~ /^SHIPPING=FEDEX;/;
94print "ok 4\n";
95
96print $c->as_string;
97
98
99# Second Example transaction sequence:
100#
101# Assume all mappings from above have been cleared.
102#
103# Client receives:
104#
105# Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/
106#
107# When client requests a URL in path "/" on this server, it sends:
108#
109# Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001
110#
111# Client receives:
112#
113# Set-Cookie: PART_NUMBER=RIDING_ROCKET_0023; path=/ammo
114#
115# When client requests a URL in path "/ammo" on this server, it sends:
116#
117# Cookie: PART_NUMBER=RIDING_ROCKET_0023; PART_NUMBER=ROCKET_LAUNCHER_0001
118#
119# NOTE: There are two name/value pairs named "PART_NUMBER" due to
120# the inheritance of the "/" mapping in addition to the "/ammo" mapping.
121
122$c = HTTP::Cookies->new; # clear it
123
124$req = HTTP::Request->new(GET => "http://www.acme.com/");
125$res = HTTP::Response->new(200, "OK");
126$res->request($req);
127$res->header("Set-Cookie", "PART_NUMBER=ROCKET_LAUNCHER_0001; path=/");
128
129$c->extract_cookies($res);
130
131$req = HTTP::Request->new(GET => "http://www.acme.com/");
132$c->add_cookie_header($req);
133
134print "not " unless $req->header("Cookie") eq "PART_NUMBER=ROCKET_LAUNCHER_0001";
135print "ok 5\n";
136
137$res->request($req);
138$res->header("Set-Cookie", "PART_NUMBER=RIDING_ROCKET_0023; path=/ammo");
139$c->extract_cookies($res);
140
141$req = HTTP::Request->new(GET => "http://www.acme.com/ammo");
142$c->add_cookie_header($req);
143
144print "not " unless $req->header("Cookie") =~
145 /^PART_NUMBER=RIDING_ROCKET_0023;\s*PART_NUMBER=ROCKET_LAUNCHER_0001/;
146print "ok 6\n";
147
148print $c->as_string;
149undef($c);
150
151
152#-------------------------------------------------------------------
153# When there are no "Set-Cookie" header, then even responses
154# without any request URLs connected should be allowed.
155
156$c = HTTP::Cookies->new;
157$c->extract_cookies(HTTP::Response->new("200", "OK"));
158print "not " if count_cookies($c) != 0;
159print "ok 7\n";
160
161
162#-------------------------------------------------------------------
163# Then we test with the examples from draft-ietf-http-state-man-mec-03.txt
164#
165# 5. EXAMPLES
166
167$c = HTTP::Cookies->new;
168
169#
170# 5.1 Example 1
171#
172# Most detail of request and response headers has been omitted. Assume
173# the user agent has no stored cookies.
174#
175# 1. User Agent -> Server
176#
177# POST /acme/login HTTP/1.1
178# [form data]
179#
180# User identifies self via a form.
181#
182# 2. Server -> User Agent
183#
184# HTTP/1.1 200 OK
185# Set-Cookie2: Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"
186#
187# Cookie reflects user's identity.
188
189$cookie = interact($c, 'http://www.acme.com/acme/login',
190 'Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"');
191print "not " if $cookie;
192print "ok 8\n";
193
194#
195# 3. User Agent -> Server
196#
197# POST /acme/pickitem HTTP/1.1
198# Cookie: $Version="1"; Customer="WILE_E_COYOTE"; $Path="/acme"
199# [form data]
200#
201# User selects an item for ``shopping basket.''
202#
203# 4. Server -> User Agent
204#
205# HTTP/1.1 200 OK
206# Set-Cookie2: Part_Number="Rocket_Launcher_0001"; Version="1";
207# Path="/acme"
208#
209# Shopping basket contains an item.
210
211$cookie = interact($c, 'http://www.acme.com/acme/pickitem',
212 'Part_Number="Rocket_Launcher_0001"; Version="1"; Path="/acme"');
213print "not " unless $cookie =~ m(^\$Version="?1"?; Customer="?WILE_E_COYOTE"?; \$Path="/acme"$);
214print "ok 9\n";
215
216#
217# 5. User Agent -> Server
218#
219# POST /acme/shipping HTTP/1.1
220# Cookie: $Version="1";
221# Customer="WILE_E_COYOTE"; $Path="/acme";
222# Part_Number="Rocket_Launcher_0001"; $Path="/acme"
223# [form data]
224#
225# User selects shipping method from form.
226#
227# 6. Server -> User Agent
228#
229# HTTP/1.1 200 OK
230# Set-Cookie2: Shipping="FedEx"; Version="1"; Path="/acme"
231#
232# New cookie reflects shipping method.
233
234$cookie = interact($c, "http://www.acme.com/acme/shipping",
235 'Shipping="FedEx"; Version="1"; Path="/acme"');
236
237print "not " unless $cookie =~ /^\$Version="?1"?;/ &&
238 $cookie =~ /Part_Number="?Rocket_Launcher_0001"?;\s*\$Path="\/acme"/ &&
239 $cookie =~ /Customer="?WILE_E_COYOTE"?;\s*\$Path="\/acme"/;
240print "ok 10\n";
241
242#
243# 7. User Agent -> Server
244#
245# POST /acme/process HTTP/1.1
246# Cookie: $Version="1";
247# Customer="WILE_E_COYOTE"; $Path="/acme";
248# Part_Number="Rocket_Launcher_0001"; $Path="/acme";
249# Shipping="FedEx"; $Path="/acme"
250# [form data]
251#
252# User chooses to process order.
253#
254# 8. Server -> User Agent
255#
256# HTTP/1.1 200 OK
257#
258# Transaction is complete.
259
260$cookie = interact($c, "http://www.acme.com/acme/process");
261print "FINAL COOKIE: $cookie\n";
262print "not " unless $cookie =~ /Shipping="?FedEx"?;\s*\$Path="\/acme"/ &&
263 $cookie =~ /WILE_E_COYOTE/;
264print "ok 11\n";
265
266#
267# The user agent makes a series of requests on the origin server, after
268# each of which it receives a new cookie. All the cookies have the same
269# Path attribute and (default) domain. Because the request URLs all have
270# /acme as a prefix, and that matches the Path attribute, each request
271# contains all the cookies received so far.
272
273print $c->as_string;
274
275
276# 5.2 Example 2
277#
278# This example illustrates the effect of the Path attribute. All detail
279# of request and response headers has been omitted. Assume the user agent
280# has no stored cookies.
281
282$c = HTTP::Cookies->new;
283
284# Imagine the user agent has received, in response to earlier requests,
285# the response headers
286#
287# Set-Cookie2: Part_Number="Rocket_Launcher_0001"; Version="1";
288# Path="/acme"
289#
290# and
291#
292# Set-Cookie2: Part_Number="Riding_Rocket_0023"; Version="1";
293# Path="/acme/ammo"
294
295interact($c, "http://www.acme.com/acme/ammo/specific",
296 'Part_Number="Rocket_Launcher_0001"; Version="1"; Path="/acme"',
297 'Part_Number="Riding_Rocket_0023"; Version="1"; Path="/acme/ammo"');
298
299# A subsequent request by the user agent to the (same) server for URLs of
300# the form /acme/ammo/... would include the following request header:
301#
302# Cookie: $Version="1";
303# Part_Number="Riding_Rocket_0023"; $Path="/acme/ammo";
304# Part_Number="Rocket_Launcher_0001"; $Path="/acme"
305#
306# Note that the NAME=VALUE pair for the cookie with the more specific Path
307# attribute, /acme/ammo, comes before the one with the less specific Path
308# attribute, /acme. Further note that the same cookie name appears more
309# than once.
310
311$cookie = interact($c, "http://www.acme.com/acme/ammo/...");
312print "not " unless $cookie =~ /Riding_Rocket_0023.*Rocket_Launcher_0001/;
313print "ok 12\n";
314
315# A subsequent request by the user agent to the (same) server for a URL of
316# the form /acme/parts/ would include the following request header:
317#
318# Cookie: $Version="1"; Part_Number="Rocket_Launcher_0001"; $Path="/acme"
319#
320# Here, the second cookie's Path attribute /acme/ammo is not a prefix of
321# the request URL, /acme/parts/, so the cookie does not get forwarded to
322# the server.
323
324$cookie = interact($c, "http://www.acme.com/acme/parts/");
325print "not " unless $cookie =~ /Rocket_Launcher_0001/ &&
326 $cookie !~ /Riding_Rocket_0023/;
327print "ok 13\n";
328
329print $c->as_string;
330
331#-----------------------------------------------------------------------
332
333# Test rejection of Set-Cookie2 responses based on domain, path or port
334
335$c = HTTP::Cookies->new;
336
337# illegal domain (no embedded dots)
338$cookie = interact($c, "http://www.acme.com", 'foo=bar; domain=".com"');
339print "not " if count_cookies($c) > 0;
340print "ok 14\n";
341
342# legal domain
343$cookie = interact($c, "http://www.acme.com", 'foo=bar; domain="acme.com"');
344print "not " if count_cookies($c) != 1;
345print "ok 15\n";
346
347# illegal domain (host prefix "www.a" contains a dot)
348$cookie = interact($c, "http://www.a.acme.com", 'foo=bar; domain="acme.com"');
349print "not " if count_cookies($c) != 1;
350print "ok 16\n";
351
352# legal domain
353$cookie = interact($c, "http://www.a.acme.com", 'foo=bar; domain=".a.acme.com"');
354print "not " if count_cookies($c) != 2;
355print "ok 17\n";
356
357# can't use a IP-address as domain
358$cookie = interact($c, "http://125.125.125.125", 'foo=bar; domain="125.125.125"');
359print "not " if count_cookies($c) != 2;
360print "ok 18\n";
361
362# illegal path (must be prefix of request path)
363$cookie = interact($c, "http://www.sol.no", 'foo=bar; domain=".sol.no"; path="/foo"');
364print "not " if count_cookies($c) != 2;
365print "ok 19\n";
366
367# legal path
368$cookie = interact($c, "http://www.sol.no/foo/bar", 'foo=bar; domain=".sol.no"; path="/foo"');
369print "not " if count_cookies($c) != 3;
370print "ok 20\n";
371
372# illegal port (request-port not in list)
373$cookie = interact($c, "http://www.sol.no", 'foo=bar; domain=".sol.no"; port="90,100"');
374print "not " if count_cookies($c) != 3;
375print "ok 21\n";
376
377# legal port
378$cookie = interact($c, "http://www.sol.no", 'foo=bar; domain=".sol.no"; port="90,100, 80,8080"; max-age=100; Comment = "Just kidding! (\"|\\\\) "');
379print "not " if count_cookies($c) != 4;
380print "ok 22\n";
381
382# port attribute without any value (current port)
383$cookie = interact($c, "http://www.sol.no", 'foo9=bar; domain=".sol.no"; port; max-age=100;');
384print "not " if count_cookies($c) != 5;
385print "ok 23\n";
386
387# encoded path
388$cookie = interact($c, "http://www.sol.no/foo/", 'foo8=bar; path="/%66oo"');
389print "not " if count_cookies($c) != 6;
390print "ok 24\n";
391
392my $file = "lwp-cookies-$$.txt";
393$c->save($file);
394$old = $c->as_string;
395undef($c);
396
397$c = HTTP::Cookies->new;
398$c->load($file);
399unlink($file) || warn "Can't unlink $file: $!";
400
401print "not " unless $old eq $c->as_string;
402print "ok 25\n";
403
404undef($c);
405
406#
407# Try some URL encodings of the PATHs
408#
409$c = HTTP::Cookies->new;
410interact($c, "http://www.acme.com/foo%2f%25/%40%40%0Anew%E5/%E5", 'foo = bar; version = 1');
411print $c->as_string;
412
413$cookie = interact($c, "http://www.acme.com/foo%2f%25/@@%0anewå/æøå", "bar=baz; path=\"/foo/\"; version=1");
414print "not " unless $cookie =~ /foo=bar/ && $cookie =~ /^\$version=\"?1\"?/i;
415print "ok 26\n";
416
417$cookie = interact($c, "http://www.acme.com/foo/%25/@@%0anewå/æøå");
418print "not " if $cookie;
419print "ok 27\n";
420
421undef($c);
422
423#
424# Try to use the Netscape cookie file format for saving
425#
426$file = "cookies-$$.txt";
427$c = HTTP::Cookies::Netscape->new(file => $file);
428interact($c, "http://www.acme.com/", "foo1=bar; max-age=100");
429interact($c, "http://www.acme.com/", "foo2=bar; port=\"80\"; max-age=100; Discard; Version=1");
430interact($c, "http://www.acme.com/", "foo3=bar; secure; Version=1");
431$c->save;
432undef($c);
433
434$c = HTTP::Cookies::Netscape->new(file => $file);
435print "not " unless count_cookies($c) == 1; # 2 of them discarded on save
436print "ok 28\n";
437
438print "not " unless $c->as_string =~ /foo1=bar/;
439print "ok 29\n";
440undef($c);
441unlink($file);
442
443
444#
445# Some additional Netscape cookies test
446#
447$c = HTTP::Cookies->new;
448$req = HTTP::Request->new(POST => "http://foo.bar.acme.com/foo");
449
450# Netscape allows a host part that contains dots
451$res = HTTP::Response->new(200, "OK");
452$res->header(set_cookie => 'Customer=WILE_E_COYOTE; domain=.acme.com');
453$res->request($req);
454$c->extract_cookies($res);
455
456# and that the domain is the same as the host without adding a leading
457# dot to the domain. Should not quote even if strange chars are used
458# in the cookie value.
459$res = HTTP::Response->new(200, "OK");
460$res->header(set_cookie => 'PART_NUMBER=3,4; domain=foo.bar.acme.com');
461$res->request($req);
462$c->extract_cookies($res);
463
464print $c->as_string;
465
466$req = HTTP::Request->new(POST => "http://foo.bar.acme.com/foo");
467$c->add_cookie_header($req);
468#print $req->as_string;
469print "not " unless $req->header("Cookie") =~ /PART_NUMBER=3,4/ &&
470 $req->header("Cookie") =~ /Customer=WILE_E_COYOTE/;
471print "ok 30\n";
472
473
474
475# Test handling of local intranet hostnames without a dot
476$c->clear;
477print "---\n";
478#require LWP::Debug;
479#LWP::Debug::level('+');
480
481interact($c, "http://example/", "foo1=bar; PORT; Discard;");
482$_=interact($c, "http://example/", 'foo2=bar; domain=".local"');
483print "not " unless /foo1=bar/;
484print "ok 31\n";
485
486$_=interact($c, "http://example/", 'foo3=bar');
487$_=interact($c, "http://example/");
488print "Cookie: $_\n";
489print "not " unless /foo2=bar/ && count_cookies($c) == 3;
490print "ok 32\n";
491print $c->as_string;
492
493#-------------------------------------------------------------------
494
495sub interact
496{
497 my $c = shift;
498 my $url = shift;
499 my $req = HTTP::Request->new(POST => $url);
500 $c->add_cookie_header($req);
501 my $cookie = $req->header("Cookie");
502 my $res = HTTP::Response->new(200, "OK");
503 $res->request($req);
504 for (@_) { $res->push_header("Set-Cookie2" => $_) }
505 $c->extract_cookies($res);
506 return $cookie;
507}
508
509sub count_cookies
510{
511 my $c = shift;
512 my $no = 0;
513 $c->scan(sub { $no++ });
514 $no;
515}
Note: See TracBrowser for help on using the repository browser.