Added more documentation and tests
[catagits/HTTP-Request-AsCGI.git] / lib / HTTP / Request / AsCGI.pm
CommitLineData
b2e1304d 1package HTTP::Request::AsCGI;
2
3use strict;
4use warnings;
090cc060 5use bytes;
b2e1304d 6use base 'Class::Accessor::Fast';
7
26e3d92b 8use Carp qw[croak];
9use HTTP::Response qw[];
5889d784 10use IO::File qw[SEEK_SET];
26e3d92b 11use Symbol qw[];
9c216915 12use URI::Escape qw[];
b2e1304d 13
14f243e8 14__PACKAGE__->mk_accessors( qw[ is_setup
5889d784 15 is_prepared
16 is_restored
17
18 should_dup
19 should_restore
20 should_rewind
21 should_setup_content
22
23 environment
24 request
25 stdin
26 stdout
27 stderr ] );
b2e1304d 28
26e3d92b 29our $VERSION = 0.6_01;
b2e1304d 30
31sub new {
26e3d92b 32 my $class = ref $_[0] ? ref shift : shift;
33 my $params = {};
4e0afe7d 34
26e3d92b 35 if ( @_ % 2 == 0 ) {
36 $params = { @_ };
37 }
38 else {
39 $params = { request => shift, environment => { @_ } };
40 }
41
42 return bless( {}, $class )->initialize($params);
43}
44
45sub initialize {
46 my ( $self, $params ) = @_;
47
48 if ( exists $params->{request} ) {
49 $self->request( $params->{request} );
50 }
51 else {
52 croak("Mandatory parameter 'request' is missing.");
2d51e42f 53 }
4e0afe7d 54
26e3d92b 55 if ( exists $params->{environment} ) {
14f243e8 56 $self->environment( { %{ $params->{environment} } } );
26e3d92b 57 }
58 else {
59 $self->environment( {} );
60 }
61
62 if ( exists $params->{stdin} ) {
63 $self->stdin( $params->{stdin} );
64 }
65 else {
66 $self->stdin( IO::File->new_tmpfile );
67 }
68
69 if ( exists $params->{stdout} ) {
70 $self->stdout( $params->{stdout} );
71 }
72 else {
73 $self->stdout( IO::File->new_tmpfile );
74 }
75
76 if ( exists $params->{stderr} ) {
77 $self->stderr( $params->{stderr} );
78 }
4d6e304a 79
26e3d92b 80 if ( exists $params->{dup} ) {
81 $self->should_dup( $params->{dup} ? 1 : 0 );
82 }
83 else {
84 $self->should_dup(1);
4d6e304a 85 }
26e3d92b 86
87 if ( exists $params->{restore} ) {
88 $self->should_restore( $params->{restore} ? 1 : 0 );
89 }
90 else {
91 $self->should_restore(1);
92 }
93
94 if ( exists $params->{rewind} ) {
95 $self->should_rewind( $params->{rewind} ? 1 : 0 );
96 }
97 else {
98 $self->should_rewind(1);
99 }
100
5889d784 101 if ( exists $params->{content} ) {
102 $self->should_setup_content( $params->{content} ? 1 : 0 );
103 }
104 else {
105 $self->should_setup_content(1);
106 }
107
26e3d92b 108 $self->prepare;
109
110 return $self;
111}
112
113*enviroment = \&environment;
114
115sub has_stdin { return defined $_[0]->stdin }
116sub has_stdout { return defined $_[0]->stdout }
117sub has_stderr { return defined $_[0]->stderr }
118
9c216915 119my $HTTP_Token = qr/[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7A\x7C\x7E]/;
120my $HTTP_Version = qr/HTTP\/[0-9]+\.[0-9]+/;
121
26e3d92b 122sub prepare {
123 my $self = shift;
124
125 my $environment = $self->environment;
126 my $request = $self->request;
b2e1304d 127
30efa07d 128 my $host = $request->header('Host');
129 my $uri = $request->uri->clone;
26e3d92b 130
30efa07d 131 $uri->scheme('http') unless $uri->scheme;
132 $uri->host('localhost') unless $uri->host;
133 $uri->port(80) unless $uri->port;
a3875fc6 134 $uri->host_port($host) unless !$host || ( $host eq $uri->host_port );
4e0afe7d 135
ca38286c 136 $uri = $uri->canonical;
30efa07d 137
26e3d92b 138 my %cgi = (
b2e1304d 139 GATEWAY_INTERFACE => 'CGI/1.1',
30efa07d 140 HTTP_HOST => $uri->host_port,
a3875fc6 141 HTTPS => ( $uri->scheme eq 'https' ) ? 'ON' : 'OFF', # not in RFC 3875
9c216915 142 PATH_INFO => URI::Escape::uri_unescape($uri->path),
a3875fc6 143 QUERY_STRING => $uri->query || '',
144 SCRIPT_NAME => '/',
145 SERVER_NAME => $uri->host,
146 SERVER_PORT => $uri->port,
147 SERVER_PROTOCOL => $request->protocol || 'HTTP/1.1',
148 SERVER_SOFTWARE => "HTTP-Request-AsCGI/$VERSION",
149 REMOTE_ADDR => '127.0.0.1',
150 REMOTE_HOST => 'localhost',
151 REMOTE_PORT => int( rand(64000) + 1000 ), # not in RFC 3875
152 REQUEST_URI => $uri->path_query, # not in RFC 3875
26e3d92b 153 REQUEST_METHOD => $request->method
154 );
b2e1304d 155
9c216915 156 if ( my $authorization = $request->header('Authorization') ) {
157
158 ( my $scheme ) = $authorization =~ /^($HTTP_Token+)/o;
159
160 if ( $scheme =~ /^Basic/i ) {
161
162 if ( ( my $username ) = $request->headers->authorization_basic ) {
163 $cgi{AUTH_TYPE} = 'Basic';
164 $cgi{REMOTE_USER} = $username;
165 }
166 }
167 elsif ( $scheme =~ /^Digest/i ) {
168
169 if ( ( my $username ) = $authorization =~ /username="([^"]+)"/ ) {
170 $cgi{AUTH_TYPE} = 'Digest';
171 $cgi{REMOTE_USER} = $username;
172 }
173 }
174 }
175
26e3d92b 176 foreach my $key ( keys %cgi ) {
177
178 unless ( exists $environment->{ $key } ) {
179 $environment->{ $key } = $cgi{ $key };
180 }
181 }
182
9c216915 183 foreach my $field ( $request->headers->header_field_names ) {
b2e1304d 184
ca38286c 185 my $key = uc("HTTP_$field");
2aaf55bc 186 $key =~ tr/-/_/;
ca38286c 187 $key =~ s/^HTTP_// if $field =~ /^Content-(Length|Type)$/;
b2e1304d 188
26e3d92b 189 unless ( exists $environment->{ $key } ) {
9c216915 190 $environment->{ $key } = $request->headers->header($field);
b2e1304d 191 }
192 }
193
9c216915 194 if ( $environment->{SCRIPT_NAME} ne '/' && $environment->{PATH_INFO} ) {
26e3d92b 195 $environment->{PATH_INFO} =~ s/^\Q$environment->{SCRIPT_NAME}\E/\//;
196 $environment->{PATH_INFO} =~ s/^\/+/\//;
197 }
198
199 $self->is_prepared(1);
200}
201
202sub setup {
203 my $self = shift;
204
14f243e8 205 if ( $self->is_setup ) {
9c216915 206 croak( 'An attempt was made to setup environment variables and '
207 . 'standard filehandles which has already been setup.' );
474703e4 208 }
474703e4 209
14f243e8 210 if ( $self->should_setup_content && $self->has_stdin ) {
9c216915 211 $self->setup_content;
5889d784 212 }
5889d784 213
214 if ( $self->has_stdin ) {
26e3d92b 215
216 if ( $self->should_dup ) {
217
218 if ( $self->should_restore ) {
219
220 open( my $stdin, '<&STDIN' )
221 or croak("Couldn't dup STDIN: '$!'");
222
223 $self->{restore}->{stdin} = $stdin;
224 }
225
14f243e8 226 open( STDIN, '<&' . fileno($self->stdin) )
9c216915 227 or croak("Couldn't dup stdin filehandle to STDIN: '$!'");
26e3d92b 228 }
229 else {
230
231 my $stdin = Symbol::qualify_to_ref('STDIN');
232
233 if ( $self->should_restore ) {
234
235 $self->{restore}->{stdin} = *$stdin;
236 $self->{restore}->{stdin_ref} = \*$stdin;
237 }
b2e1304d 238
5889d784 239 *$stdin = $self->stdin;
26e3d92b 240 }
b2e1304d 241
5889d784 242 binmode( $self->stdin );
26e3d92b 243 binmode( STDIN );
b2e1304d 244 }
26e3d92b 245
246 if ( $self->has_stdout ) {
b2e1304d 247
26e3d92b 248 if ( $self->should_dup ) {
ca38286c 249
26e3d92b 250 if ( $self->should_restore ) {
251
252 open( my $stdout, '>&STDOUT' )
253 or croak("Couldn't dup STDOUT: '$!'");
254
255 $self->{restore}->{stdout} = $stdout;
256 }
257
14f243e8 258 open( STDOUT, '>&' . fileno($self->stdout) )
9c216915 259 or croak("Couldn't dup stdout filehandle to STDOUT: '$!'");
26e3d92b 260 }
261 else {
30efa07d 262
26e3d92b 263 my $stdout = Symbol::qualify_to_ref('STDOUT');
090cc060 264
26e3d92b 265 if ( $self->should_restore ) {
441eeb04 266
26e3d92b 267 $self->{restore}->{stdout} = *$stdout;
268 $self->{restore}->{stdout_ref} = \*$stdout;
269 }
76391122 270
5889d784 271 *$stdout = $self->stdout;
26e3d92b 272 }
76391122 273
a3875fc6 274 binmode( $self->stdout );
275 binmode( STDOUT);
276 }
30efa07d 277
26e3d92b 278 if ( $self->has_stderr ) {
090cc060 279
26e3d92b 280 if ( $self->should_dup ) {
441eeb04 281
26e3d92b 282 if ( $self->should_restore ) {
090cc060 283
26e3d92b 284 open( my $stderr, '>&STDERR' )
285 or croak("Couldn't dup STDERR: '$!'");
4e0afe7d 286
26e3d92b 287 $self->{restore}->{stderr} = $stderr;
288 }
b2e1304d 289
14f243e8 290 open( STDERR, '>&' . fileno($self->stderr) )
9c216915 291 or croak("Couldn't dup stdout filehandle to STDOUT: '$!'");
26e3d92b 292 }
293 else {
b2e1304d 294
26e3d92b 295 my $stderr = Symbol::qualify_to_ref('STDERR');
296
297 if ( $self->should_restore ) {
298
299 $self->{restore}->{stderr} = *$stderr;
300 $self->{restore}->{stderr_ref} = \*$stderr;
301 }
302
5889d784 303 *$stderr = $self->stderr;
26e3d92b 304 }
305
306 binmode( $self->stderr );
307 binmode( STDERR );
308 }
b2e1304d 309
9c216915 310 {
311 no warnings 'uninitialized';
5889d784 312
9c216915 313 if ( $self->should_restore ) {
314 $self->{restore}->{environment} = { %ENV };
315 }
5889d784 316
9c216915 317 %ENV = %{ $self->environment };
5889d784 318 }
319
9c216915 320 if ( $INC{'CGI.pm'} ) {
321 CGI::initialize_globals();
322 }
323
324 $self->is_setup(1);
325
326 return $self;
5889d784 327}
328
9c216915 329sub setup_content {
330 my $self = shift;
331 my $stdin = shift || $self->stdin;
332
333 my $content = $self->request->content_ref;
334
335 if ( ref($content) eq 'SCALAR' ) {
336
337 if ( defined($$content) && length($$content) ) {
338
339 print( { $stdin } $$content )
340 or croak("Couldn't write request content SCALAR to stdin filehandle: '$!'");
341
342 if ( $self->should_rewind ) {
343
344 seek( $stdin, 0, SEEK_SET )
345 or croak("Couldn't rewind stdin filehandle: '$!'");
346 }
347 }
348 }
349 elsif ( ref($content) eq 'CODE' ) {
350
351 while () {
352
353 my $chunk = &$content();
354
355 if ( defined($chunk) && length($chunk) ) {
356
357 print( { $stdin } $chunk )
358 or croak("Couldn't write request content callback to stdin filehandle: '$!'");
359 }
360 else {
361 last;
362 }
363 }
364
365 if ( $self->should_rewind ) {
366
367 seek( $stdin, 0, SEEK_SET )
368 or croak("Couldn't rewind stdin filehandle: '$!'");
369 }
370 }
371 else {
372 croak("Couldn't write request content to stdin filehandle: 'Unknown request content $content'");
373 }
374}
474703e4 375
780060e5 376sub response {
4d6e304a 377 my $self = shift;
378 my %params = ( headers_only => 0, sync => 0, @_ );
780060e5 379
6faa5a50 380 return undef unless $self->has_stdout;
780060e5 381
5889d784 382 if ( $self->should_rewind ) {
383
384 seek( $self->stdout, 0, SEEK_SET )
9c216915 385 or croak("Couldn't rewind stdout filehandle: '$!'");
5889d784 386 }
780060e5 387
6faa5a50 388 my $message = undef;
389 my $response = HTTP::Response->new( 200, 'OK' );
390 $response->protocol('HTTP/1.1');
391
474703e4 392 while ( my $line = readline($self->stdout) ) {
14f243e8 393
394 if ( !$message && $line =~ /^\x0d?\x0a$/ ) {
395 next;
396 }
397 else {
398 $message .= $line;
399 }
400
6faa5a50 401 last if $message =~ /\x0d?\x0a\x0d?\x0a$/;
780060e5 402 }
26e3d92b 403
6faa5a50 404 if ( !$message ) {
6faa5a50 405 $response->code(500);
406 $response->message('Internal Server Error');
474703e4 407 $response->date( time() );
6faa5a50 408 $response->content( $response->error_as_HTML );
409 $response->content_type('text/html');
410 $response->content_length( length $response->content );
decf17dc 411
6faa5a50 412 return $response;
780060e5 413 }
414
474703e4 415 if ( $message =~ s/^($HTTP_Version)[\x09\x20]+(\d\d\d)[\x09\x20]+([\x20-\xFF]*)\x0D?\x0A//o ) {
6faa5a50 416 $response->protocol($1);
417 $response->code($2);
418 $response->message($3);
4e0afe7d 419 }
decf17dc 420
6faa5a50 421 $message =~ s/\x0D?\x0A[\x09\x20]+/\x20/gs;
decf17dc 422
6faa5a50 423 foreach ( split /\x0D?\x0A/, $message ) {
780060e5 424
474703e4 425 s/[\x09\x20]*$//;
426
427 if ( /^($HTTP_Token+)[\x09\x20]*:[\x09\x20]*([\x20-\xFF]+)$/o ) {
6faa5a50 428 $response->headers->push_header( $1 => $2 );
429 }
430 else {
431 # XXX what should we do on bad headers?
432 }
780060e5 433 }
26e3d92b 434
6faa5a50 435 my $status = $response->header('Status');
780060e5 436
474703e4 437 if ( $status && $status =~ /^(\d\d\d)[\x09\x20]+([\x20-\xFF]+)$/ ) {
6faa5a50 438 $response->code($1);
439 $response->message($2);
440 }
4e0afe7d 441
6faa5a50 442 if ( !$response->date ) {
14f243e8 443 $response->date(time());
4e0afe7d 444 }
780060e5 445
4d6e304a 446 if ( $params{headers_only} ) {
4e0afe7d 447
4d6e304a 448 if ( $params{sync} ) {
4e0afe7d 449
4d6e304a 450 my $position = tell( $self->stdout )
9c216915 451 or croak("Couldn't get file position from stdout filehandle: '$!'");
4e0afe7d 452
4d6e304a 453 sysseek( $self->stdout, $position, SEEK_SET )
9c216915 454 or croak("Couldn't seek stdout filehandle: '$!'");
4d6e304a 455 }
4e0afe7d 456
4d6e304a 457 return $response;
780060e5 458 }
4e0afe7d 459
4d6e304a 460 my $content = undef;
461 my $content_length = 0;
462
463 while () {
464
474703e4 465 my $r = read( $self->stdout, $content, 65536, $content_length );
4e0afe7d 466
4d6e304a 467 if ( defined $r ) {
468
474703e4 469 if ( $r == 0 ) {
470 last;
471 }
472 else {
473 $content_length += $r;
474 }
4d6e304a 475 }
476 else {
9c216915 477 croak("Couldn't read response content from stdin filehandle: '$!'");
780060e5 478 }
4d6e304a 479 }
480
481 if ( $content_length ) {
482
483 $response->content_ref(\$content);
4e0afe7d 484
4d6e304a 485 if ( !$response->content_length ) {
486 $response->content_length($content_length);
decf17dc 487 }
780060e5 488 }
489
780060e5 490 return $response;
491}
492
b2e1304d 493sub restore {
494 my $self = shift;
4e0afe7d 495
14f243e8 496 if ( !$self->should_restore ) {
9c216915 497 croak( 'An attempt was made to restore environment variables and '
498 . 'standard filehandles which has not been saved.' );
14f243e8 499 }
26e3d92b 500
14f243e8 501 if ( !$self->is_setup ) {
9c216915 502 croak( 'An attempt was made to restore environment variables and '
503 . 'standard filehandles which has not been setup.' );
14f243e8 504 }
26e3d92b 505
14f243e8 506 if ( $self->is_restored ) {
9c216915 507 croak( 'An attempt was made to restore environment variables and '
508 . 'standard filehandles which has already been restored.' );
cef1c068 509 }
b2e1304d 510
9c216915 511 {
512 no warnings 'uninitialized';
513 %ENV = %{ $self->{restore}->{environment} };
514 }
12852959 515
26e3d92b 516 if ( $self->has_stdin ) {
30efa07d 517
26e3d92b 518 my $stdin = $self->{restore}->{stdin};
30efa07d 519
26e3d92b 520 if ( $self->should_dup ) {
521
14f243e8 522 STDIN->fdopen( fileno($stdin), '<' )
26e3d92b 523 or croak("Couldn't restore STDIN: '$!'");
524 }
525 else {
526
527 my $stdin_ref = $self->{restore}->{stdin_ref};
5889d784 528 *$stdin_ref = $stdin;
26e3d92b 529 }
090cc060 530
26e3d92b 531 if ( $self->should_rewind ) {
532
533 seek( $self->stdin, 0, SEEK_SET )
9c216915 534 or croak("Couldn't rewind stdin filehandle: '$!'");
26e3d92b 535 }
a3875fc6 536 }
26e3d92b 537
538 if ( $self->has_stdout ) {
539
540 my $stdout = $self->{restore}->{stdout};
541
542 if ( $self->should_dup ) {
543
544 STDOUT->flush
545 or croak("Couldn't flush STDOUT: '$!'");
546
14f243e8 547 STDOUT->fdopen( fileno($stdout), '>' )
26e3d92b 548 or croak("Couldn't restore STDOUT: '$!'");
549 }
550 else {
12852959 551
26e3d92b 552 my $stdout_ref = $self->{restore}->{stdout_ref};
5889d784 553 *$stdout_ref = $stdout;
26e3d92b 554 }
30efa07d 555
26e3d92b 556 if ( $self->should_rewind ) {
090cc060 557
26e3d92b 558 seek( $self->stdout, 0, SEEK_SET )
9c216915 559 or croak("Couldn't rewind stdout filehandle: '$!'");
26e3d92b 560 }
6f5fb9a7 561 }
090cc060 562
26e3d92b 563 if ( $self->has_stderr ) {
564
565 my $stderr = $self->{restore}->{stderr};
566
567 if ( $self->should_dup ) {
568
569 STDERR->flush
570 or croak("Couldn't flush STDERR: '$!'");
571
14f243e8 572 STDERR->fdopen( fileno($stderr), '>' )
26e3d92b 573 or croak("Couldn't restore STDERR: '$!'");
574 }
575 else {
576
577 my $stderr_ref = $self->{restore}->{stderr_ref};
5889d784 578 *$stderr_ref = $stderr;
26e3d92b 579 }
580
581 if ( $self->should_rewind ) {
582
583 seek( $self->stderr, 0, SEEK_SET )
9c216915 584 or croak("Couldn't rewind stderr filehandle: '$!'");
26e3d92b 585 }
586 }
9c216915 587
588 $self->{restore} = {};
589
590 $self->is_restored(1);
591
592 return $self;
b2e1304d 593}
594
595sub DESTROY {
596 my $self = shift;
26e3d92b 597
14f243e8 598 if ( $self->should_restore && $self->is_setup && !$self->is_restored ) {
6faa5a50 599 $self->restore;
26e3d92b 600 }
b2e1304d 601}
602
6031;
604
605__END__
606
607=head1 NAME
608
9c216915 609HTTP::Request::AsCGI - Setup a Common Gateway Interface environment from a HTTP::Request
b2e1304d 610
611=head1 SYNOPSIS
612
bd7813ac 613 use CGI;
614 use HTTP::Request;
615 use HTTP::Request::AsCGI;
26e3d92b 616
bd7813ac 617 my $request = HTTP::Request->new( GET => 'http://www.host.com/' );
618 my $stdout;
26e3d92b 619
bd7813ac 620 {
621 my $c = HTTP::Request::AsCGI->new($request)->setup;
622 my $q = CGI->new;
26e3d92b 623
bd7813ac 624 print $q->header,
625 $q->start_html('Hello World'),
626 $q->h1('Hello World'),
627 $q->end_html;
26e3d92b 628
bd7813ac 629 $stdout = $c->stdout;
26e3d92b 630
14f243e8 631 # environment and descriptors is automatically restored
2d51e42f 632 # when $c is destructed.
bd7813ac 633 }
26e3d92b 634
bd7813ac 635 while ( my $line = $stdout->getline ) {
636 print $line;
637 }
26e3d92b 638
b2e1304d 639=head1 DESCRIPTION
640
26e3d92b 641Provides a convinient way of setting up an CGI environment from a HTTP::Request.
2d51e42f 642
b2e1304d 643=head1 METHODS
644
26e3d92b 645=over 4
b2e1304d 646
14f243e8 647=item * new
648
9c216915 649Contructor, this method takes a hash of parameters. The following parameters are
650valid:
14f243e8 651
652=over 8
653
654=item * request
2d51e42f 655
14f243e8 656 request => HTTP::Request->new( GET => 'http://www.host.com/' )
657
658=item * stdin
659
9c216915 660A filehandle to be used as standard input, defaults to a temporary filehandle.
661If C<stdin> is C<undef>, standard input will be left as is.
14f243e8 662
663 stdin => IO::File->new_tmpfile
664 stdin => IO::String->new
665 stdin => $fh
666 stdin => undef
667
668=item * stdout
669
9c216915 670A filehandle to be used as standard output, defaults to a temporary filehandle.
671If C<stdout> is C<undef>, standard output will be left as is.
14f243e8 672
673 stdout => IO::File->new_tmpfile
674 stdout => IO::String->new
675 stdout => $fh
676 stdout => undef
677
678=item * stderr
679
9c216915 680A filehandle to be used as standard error, defaults to C<undef>. If C<stderr> is
681C<undef>, standard error will be left as is.
14f243e8 682
683 stderr => IO::File->new_tmpfile
684 stderr => IO::String->new
685 stderr => $fh
686 stderr => undef
687
688=item * environment
689
9c216915 690A C<HASH> of additional environment variables to be used in CGI.
691C<HTTP::Request::AsCGI> doesn't autmatically merge C<%ENV>, it has to be
692explicitly given if that is desired. Environment variables given in this
693C<HASH> isn't overridden by C<HTTP::Request::AsCGI>.
694
14f243e8 695 environment => \%ENV
9c216915 696 environment => { PATH => '/bin:/usr/bin', SERVER_SOFTWARE => 'Apache/1.3' }
697
698Following standard meta-variables (in addition to protocol-specific) is setup:
699
700 AUTH_TYPE
701 CONTENT_LENGTH
702 CONTENT_TYPE
703 GATEWAY_INTERFACE
704 PATH_INFO
705 SCRIPT_NAME
706 SERVER_NAME
707 SERVER_PORT
708 SERVER_PROTOCOL
709 SERVER_SOFTWARE
710 REMOTE_ADDR
711 REMOTE_HOST
712 REMOTE_USER
713 REQUEST_METHOD
714 QUERY_STRING
715
716Following non-standard but common meta-variables is setup:
717
718 HTTPS
719 REMOTE_PORT
720 REQUEST_URI
721
722Following meta-variables is B<not> setup but B<must> be provided in CGI:
723
724 PATH_TRANSLATED
725
726Following meta-variables is B<not> setup but common in CGI:
727
728 DOCUMENT_ROOT
729 SCRIPT_FILENAME
730 SERVER_ROOT
14f243e8 731
732=item * dup
733
9c216915 734Boolean to indicate whether to C<dup> standard filehandle or to assign the
735typeglob representing the standard filehandle. Defaults to C<true>.
736
14f243e8 737 dup => 0
738 dup => 1
739
740=item * restore
741
9c216915 742Boolean to indicate whether or not to restore environment variables and standard
743filehandles. Defaults to C<true>.
744
14f243e8 745 restore => 0
746 restore => 1
747
9c216915 748If C<true> standard filehandles and environment variables will be saved duiring
749C<setup> for later use in C<restore>.
750
14f243e8 751=item * rewind
752
9c216915 753Boolean to indicate whether or not to rewind standard filehandles. Defaults
754to C<true>.
755
14f243e8 756 rewind => 0
757 rewind => 1
758
759=item * content
760
9c216915 761Boolean to indicate whether or not to request content should be written to
762C<stdin> filehandle when C<setup> is invoked. Defaults to C<true>.
763
14f243e8 764 content => 0
765 content => 1
766
767=back
b2e1304d 768
9c216915 769=item * setup
bd7813ac 770
9c216915 771Attempts to setup standard filehandles and environment variables.
2d51e42f 772
9c216915 773=item * restore
b2e1304d 774
9c216915 775Attempts to restore standard filehandles and environment variables.
2d51e42f 776
9c216915 777=item * response
b2e1304d 778
9c216915 779Attempts to parse C<stdout> filehandle into a L<HTTP::Response>.
2d51e42f 780
9c216915 781=item * request
b2e1304d 782
9c216915 783Accessor for L<HTTP::Request> that was given to constructor.
2d51e42f 784
9c216915 785=item * environment
780060e5 786
9c216915 787Accessor for environment variables to be used in C<setup>.
2d51e42f 788
9c216915 789=item * stdin
b2e1304d 790
9c216915 791Accessor/Mutator for standard input filehandle.
2d51e42f 792
9c216915 793=item * stdout
b2e1304d 794
9c216915 795Accessor/Mutator for standard output filehandle.
2d51e42f 796
9c216915 797=item * stderr
b2e1304d 798
9c216915 799Accessor/Mutator for standard error filehandle.
b2e1304d 800
2d51e42f 801=back
b2e1304d 802
9c216915 803=head1 DEPRECATED
804
805XXX Constructor
806
74fbb9dd 807=head1 SEE ALSO
808
809=over 4
810
811=item examples directory in this distribution.
812
813=item L<WWW::Mechanize::CGI>
814
815=item L<Test::WWW::Mechanize::CGI>
816
817=back
818
2d51e42f 819=head1 THANKS TO
17b370b0 820
821Thomas L. Shinnick for his valuable win32 testing.
822
b2e1304d 823=head1 AUTHOR
824
825Christian Hansen, C<ch@ngmedia.com>
826
827=head1 LICENSE
828
26e3d92b 829This library is free software. You can redistribute it and/or modify
b2e1304d 830it under the same terms as perl itself.
831
832=cut