From: Hans Dieter Pearcey Date: Sun, 26 Apr 2009 23:01:45 +0000 (+0000) Subject: revert all changes since 0.5 X-Git-Tag: v1.0~21 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=b332ee65fb155a11c72da7544e44ee632c6f577d;hp=d61872c8fd0b2f3990f0f91f8fd65e61f20eff8a;p=catagits%2FHTTP-Request-AsCGI.git revert all changes since 0.5 --- diff --git a/Changes b/Changes index 873f2a2..c2a08d5 100644 --- a/Changes +++ b/Changes @@ -1,31 +1,20 @@ This file documents the revision history for Perl extension HTTP::Request::AsCGI. -0.5_01 2009-04-25 - - Added support for Perl 5.6, by Hans Dieter Pearcey (hdp@cpan.org) - - Added support for in-memory filehandles as standard filehandles - - Added support for AUTH_TYPE and REMOTE_USER, currently only support - Basic and Digest auth schemes. - - Added support for CODE in request content - - Constructor parameters has changed, "old" way of invoking constructor has - been moved to deprecation. Please see DEPRECATED section in POD. - - Added several new options to constructor for more advanced usage - - Major cleanup of internals, more readable and maintainable - - Fixed PATH_INFO, must not be urlencoded - -0.5 2006-01-20 +0.5 2006-01-20 00:00:00 2005 - Fixed bug where content was overridden on 500 responses. -0.4 2006-01-19 +0.4 2006-01-19 00:00:00 2005 - Fixed #15999 return a 500 response when message is empty, reported by Chris Dolan - Fixed Status header bug - Bumped HTTP::Response requirement to 1.53 and drop our own message parsing. -0.3 2006-01-06 +0.3 2006-01-06 00:00:00 2005 - Silence uninitialized warnings when restoring %ENV - Fixed dup and restore of STDIN. -0.2 2005-10-31 +0.2 2005-10-31 00:55:00 2005 - Added test for response. -0.1 2005-10-21 +0.1 2005-10-21 00:00:00 2005 - First release. + diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP index f67fea0..2ffcc10 100644 --- a/MANIFEST.SKIP +++ b/MANIFEST.SKIP @@ -3,7 +3,6 @@ \bCVS\b ,v$ \B\.svn\b -\B\.git\b # Avoid Makemaker generated and utility files. \bMakefile$ @@ -24,5 +23,3 @@ \.bak$ \#$ \b\.# - -^HTTP-Request-AsCGI-\d diff --git a/Makefile.PL b/Makefile.PL index cc4e84f..734551f 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -6,12 +6,11 @@ WriteMakefile( NAME => 'HTTP::Request::AsCGI', VERSION_FROM => 'lib/HTTP/Request/AsCGI.pm', PREREQ_PM => { - 'Carp' => 0, - 'Class::Accessor' => 0, - 'HTTP::Request' => 0, - 'HTTP::Response' => 1.53, - 'IO::File' => 0, - 'Test::More' => 0, - 'URI::Escape' => 0 + Carp => 0, + Class::Accessor => 0, + HTTP::Request => 0, + HTTP::Response => 1.53, + IO::File => 0, + Test::More => 0 } ); diff --git a/examples/daemon.pl b/examples/daemon.pl index bd4c235..c718487 100644 --- a/examples/daemon.pl +++ b/examples/daemon.pl @@ -18,7 +18,7 @@ my $server = HTTP::Daemon->new( LocalPort => 3000, ReuseAddr => 1 ) print "Please contact me at: url, ">\n"; while ( my $client = $server->accept ) { - + my %e = ( REMOTE_ADDR => $client->peerhost, REMOTE_HOST => $client->peerhost, @@ -53,7 +53,7 @@ while ( my $client = $server->accept ) { $q->end_form, $q->h2('Parameters'), $q->Dump, - $q->h2('Environment'), + $q->h2('Enviroment'), $q->table( $q->Tr( [ map{ $q->td( [ $_, $ENV{$_} ] ) } sort keys %ENV diff --git a/examples/synopsis.pl b/examples/synopsis.pl index 4d6847f..2106a1e 100644 --- a/examples/synopsis.pl +++ b/examples/synopsis.pl @@ -21,7 +21,7 @@ my $stdout; $stdout = $c->stdout; - # environment and descriptors will automatically be restored when $c is destructed. + # enviroment and descriptors will automatically be restored when $c is destructed. } while ( my $line = $stdout->getline ) { diff --git a/lib/HTTP/Request/AsCGI.pm b/lib/HTTP/Request/AsCGI.pm index 4a81289..380551f 100644 --- a/lib/HTTP/Request/AsCGI.pm +++ b/lib/HTTP/Request/AsCGI.pm @@ -5,129 +5,30 @@ use warnings; use bytes; use base 'Class::Accessor::Fast'; -use Carp qw[croak]; -use HTTP::Response qw[]; -use IO::File qw[SEEK_SET]; -use Symbol qw[]; -use URI::Escape qw[]; +use Carp; +use HTTP::Response; +use IO::Handle; +use IO::File; -__PACKAGE__->mk_accessors( qw[ is_setup - is_prepared - is_restored +__PACKAGE__->mk_accessors(qw[ enviroment request stdin stdout stderr ]); - should_dup - should_restore - should_rewind - should_setup_content - - environment - request - stdin - stdout - stderr ] ); - -our $VERSION = 0.5_01; +our $VERSION = 0.5; sub new { - my $class = ref $_[0] ? ref shift : shift; - my $params = {}; - - if ( @_ % 2 == 0 ) { - $params = { @_ }; - } - else { - $params = { request => shift, environment => { @_ } }; - } - - return bless( {}, $class )->initialize($params); -} - -sub initialize { - my ( $self, $params ) = @_; - - if ( exists $params->{request} ) { - $self->request( $params->{request} ); - } - else { - croak("Mandatory parameter 'request' is missing."); - } - - if ( exists $params->{environment} ) { - $self->environment( { %{ $params->{environment} } } ); - } - else { - $self->environment( {} ); - } + my $class = shift; + my $request = shift; - if ( exists $params->{stdin} ) { - $self->stdin( $params->{stdin} ); - } - else { - $self->stdin( IO::File->new_tmpfile ); + unless ( @_ % 2 == 0 && eval { $request->isa('HTTP::Request') } ) { + croak(qq/usage: $class->new( \$request [, key => value] )/); } - if ( exists $params->{stdout} ) { - $self->stdout( $params->{stdout} ); - } - else { - $self->stdout( IO::File->new_tmpfile ); - } - - if ( exists $params->{stderr} ) { - $self->stderr( $params->{stderr} ); - } - - if ( exists $params->{dup} ) { - $self->should_dup( $params->{dup} ? 1 : 0 ); - } - else { - $self->should_dup(1); - } - - if ( exists $params->{restore} ) { - $self->should_restore( $params->{restore} ? 1 : 0 ); - } - else { - $self->should_restore(1); - } - - if ( exists $params->{rewind} ) { - $self->should_rewind( $params->{rewind} ? 1 : 0 ); - } - else { - $self->should_rewind(1); - } - - if ( exists $params->{content} ) { - $self->should_setup_content( $params->{content} ? 1 : 0 ); - } - else { - $self->should_setup_content(1); - } - - $self->prepare; - - return $self; -} - -*enviroment = \&environment; - -sub has_stdin { return defined $_[0]->stdin } -sub has_stdout { return defined $_[0]->stdout } -sub has_stderr { return defined $_[0]->stderr } - -my $HTTP_Token = qr/[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7A\x7C\x7E]/; -my $HTTP_Version = qr/HTTP\/[0-9]+\.[0-9]+/; - -sub prepare { - my $self = shift; - - my $environment = $self->environment; - my $request = $self->request; + my $self = $class->SUPER::new( { restored => 0, setuped => 0 } ); + $self->request($request); + $self->stdin( IO::File->new_tmpfile ); + $self->stdout( IO::File->new_tmpfile ); my $host = $request->header('Host'); my $uri = $request->uri->clone; - $uri->scheme('http') unless $uri->scheme; $uri->host('localhost') unless $uri->host; $uri->port(80) unless $uri->port; @@ -135,11 +36,11 @@ sub prepare { $uri = $uri->canonical; - my %cgi = ( + my $enviroment = { GATEWAY_INTERFACE => 'CGI/1.1', HTTP_HOST => $uri->host_port, HTTPS => ( $uri->scheme eq 'https' ) ? 'ON' : 'OFF', # not in RFC 3875 - PATH_INFO => URI::Escape::uri_unescape($uri->path), + PATH_INFO => $uri->path, QUERY_STRING => $uri->query || '', SCRIPT_NAME => '/', SERVER_NAME => $uri->host, @@ -150,35 +51,9 @@ sub prepare { REMOTE_HOST => 'localhost', REMOTE_PORT => int( rand(64000) + 1000 ), # not in RFC 3875 REQUEST_URI => $uri->path_query, # not in RFC 3875 - REQUEST_METHOD => $request->method - ); - - if ( my $authorization = $request->header('Authorization') ) { - - ( my $scheme ) = $authorization =~ /^($HTTP_Token+)/o; - - if ( $scheme =~ /^Basic/i ) { - - if ( ( my $username ) = $request->headers->authorization_basic ) { - $cgi{AUTH_TYPE} = 'Basic'; - $cgi{REMOTE_USER} = $username; - } - } - elsif ( $scheme =~ /^Digest/i ) { - - if ( ( my $username ) = $authorization =~ /username="([^"]+)"/ ) { - $cgi{AUTH_TYPE} = 'Digest'; - $cgi{REMOTE_USER} = $username; - } - } - } - - foreach my $key ( keys %cgi ) { - - unless ( exists $environment->{ $key } ) { - $environment->{ $key } = $cgi{ $key }; - } - } + REQUEST_METHOD => $request->method, + @_ + }; foreach my $field ( $request->headers->header_field_names ) { @@ -186,122 +61,64 @@ sub prepare { $key =~ tr/-/_/; $key =~ s/^HTTP_// if $field =~ /^Content-(Length|Type)$/; - unless ( exists $environment->{ $key } ) { - $environment->{ $key } = $request->headers->header($field); + unless ( exists $enviroment->{$key} ) { + $enviroment->{$key} = $request->headers->header($field); } } - if ( $environment->{SCRIPT_NAME} ne '/' && $environment->{PATH_INFO} ) { - $environment->{PATH_INFO} =~ s/^\Q$environment->{SCRIPT_NAME}\E/\//; - $environment->{PATH_INFO} =~ s/^\/+/\//; + unless ( $enviroment->{SCRIPT_NAME} eq '/' && $enviroment->{PATH_INFO} ) { + $enviroment->{PATH_INFO} =~ s/^\Q$enviroment->{SCRIPT_NAME}\E/\//; + $enviroment->{PATH_INFO} =~ s/^\/+/\//; } - $self->is_prepared(1); + $self->enviroment($enviroment); + + return $self; } sub setup { my $self = shift; - if ( $self->is_setup ) { - croak( 'An attempt was made to setup environment variables and ' - . 'standard filehandles which has already been setup.' ); - } - - if ( $self->should_setup_content && $self->has_stdin ) { - $self->setup_content; - } - - if ( $self->has_stdin ) { - - if ( $self->should_dup ) { - - if ( $self->should_restore ) { - - open( my $stdin, '<&STDIN' ) - or croak("Couldn't dup STDIN: '$!'"); + $self->{restore}->{enviroment} = {%ENV}; - $self->{restore}->{stdin} = $stdin; - } - - open( STDIN, '<&' . fileno($self->stdin) ) - or croak("Couldn't dup stdin filehandle to STDIN: '$!'"); - } - else { - - my $stdin = Symbol::qualify_to_ref('STDIN'); + binmode( $self->stdin ); - if ( $self->should_restore ) { + if ( $self->request->content_length ) { - $self->{restore}->{stdin} = *$stdin; - $self->{restore}->{stdin_ref} = \*$stdin; - } - - *$stdin = $self->stdin; - } + syswrite( $self->stdin, $self->request->content ) + or croak("Can't write request content to stdin handle: $!"); - binmode( $self->stdin ); - binmode( STDIN ); + sysseek( $self->stdin, 0, SEEK_SET ) + or croak("Can't seek stdin handle: $!"); } - if ( $self->has_stdout ) { + open( $self->{restore}->{stdin}, '<&', STDIN->fileno ) + or croak("Can't dup stdin: $!"); - if ( $self->should_dup ) { + open( STDIN, '<&=', $self->stdin->fileno ) + or croak("Can't open stdin: $!"); - if ( $self->should_restore ) { + binmode( STDIN ); - open( my $stdout, '>&STDOUT' ) - or croak("Couldn't dup STDOUT: '$!'"); + if ( $self->stdout ) { - $self->{restore}->{stdout} = $stdout; - } + open( $self->{restore}->{stdout}, '>&', STDOUT->fileno ) + or croak("Can't dup stdout: $!"); - open( STDOUT, '>&' . fileno($self->stdout) ) - or croak("Couldn't dup stdout filehandle to STDOUT: '$!'"); - } - else { - - my $stdout = Symbol::qualify_to_ref('STDOUT'); - - if ( $self->should_restore ) { - - $self->{restore}->{stdout} = *$stdout; - $self->{restore}->{stdout_ref} = \*$stdout; - } - - *$stdout = $self->stdout; - } + open( STDOUT, '>&=', $self->stdout->fileno ) + or croak("Can't open stdout: $!"); binmode( $self->stdout ); binmode( STDOUT); } - if ( $self->has_stderr ) { + if ( $self->stderr ) { - if ( $self->should_dup ) { + open( $self->{restore}->{stderr}, '>&', STDERR->fileno ) + or croak("Can't dup stderr: $!"); - if ( $self->should_restore ) { - - open( my $stderr, '>&STDERR' ) - or croak("Couldn't dup STDERR: '$!'"); - - $self->{restore}->{stderr} = $stderr; - } - - open( STDERR, '>&' . fileno($self->stderr) ) - or croak("Couldn't dup stdout filehandle to STDOUT: '$!'"); - } - else { - - my $stderr = Symbol::qualify_to_ref('STDERR'); - - if ( $self->should_restore ) { - - $self->{restore}->{stderr} = *$stderr; - $self->{restore}->{stderr_ref} = \*$stderr; - } - - *$stderr = $self->stderr; - } + open( STDERR, '>&=', $self->stderr->fileno ) + or croak("Can't open stderr: $!"); binmode( $self->stderr ); binmode( STDERR ); @@ -309,181 +126,93 @@ sub setup { { no warnings 'uninitialized'; - - if ( $self->should_restore ) { - $self->{restore}->{environment} = { %ENV }; - } - - %ENV = %{ $self->environment }; + %ENV = %{ $self->enviroment }; } if ( $INC{'CGI.pm'} ) { CGI::initialize_globals(); } - $self->is_setup(1); + $self->{setuped}++; return $self; } -sub setup_content { - my $self = shift; - my $stdin = shift || $self->stdin; - - my $content = $self->request->content_ref; - - if ( ref($content) eq 'SCALAR' ) { - - if ( defined($$content) && length($$content) ) { - - print( { $stdin } $$content ) - or croak("Couldn't write request content SCALAR to stdin filehandle: '$!'"); - - if ( $self->should_rewind ) { - - seek( $stdin, 0, SEEK_SET ) - or croak("Couldn't rewind stdin filehandle: '$!'"); - } - } - } - elsif ( ref($content) eq 'CODE' ) { - - while () { - - my $chunk = &$content(); - - if ( defined($chunk) && length($chunk) ) { - - print( { $stdin } $chunk ) - or croak("Couldn't write request content callback to stdin filehandle: '$!'"); - } - else { - last; - } - } - - if ( $self->should_rewind ) { - - seek( $stdin, 0, SEEK_SET ) - or croak("Couldn't rewind stdin filehandle: '$!'"); - } - } - else { - croak("Couldn't write request content to stdin filehandle: 'Unknown request content $content'"); - } -} - sub response { - my $self = shift; - my %params = ( headers_only => 0, sync => 0, @_ ); - - return undef unless $self->has_stdout; + my ( $self, $callback ) = @_; - if ( $self->should_rewind ) { - - seek( $self->stdout, 0, SEEK_SET ) - or croak("Couldn't rewind stdout filehandle: '$!'"); - } + return undef unless $self->stdout; - my $message = undef; - my $response = HTTP::Response->new( 200, 'OK' ); - $response->protocol('HTTP/1.1'); - - while ( my $line = readline($self->stdout) ) { - - if ( !$message && $line =~ /^\x0d?\x0a$/ ) { - next; - } - else { - $message .= $line; - } + seek( $self->stdout, 0, SEEK_SET ) + or croak("Can't seek stdout handle: $!"); - last if $message =~ /\x0d?\x0a\x0d?\x0a$/; + my $headers; + while ( my $line = $self->stdout->getline ) { + $headers .= $line; + last if $headers =~ /\x0d?\x0a\x0d?\x0a$/; } - - if ( !$message ) { - $response->code(500); - $response->message('Internal Server Error'); - $response->date( time() ); - $response->content( $response->error_as_HTML ); - $response->content_type('text/html'); - $response->content_length( length $response->content ); - - return $response; + + unless ( defined $headers ) { + $headers = "HTTP/1.1 500 Internal Server Error\x0d\x0a"; } - if ( $message =~ s/^($HTTP_Version)[\x09\x20]+(\d\d\d)[\x09\x20]+([\x20-\xFF]*)\x0D?\x0A//o ) { - $response->protocol($1); - $response->code($2); - $response->message($3); + unless ( $headers =~ /^HTTP/ ) { + $headers = "HTTP/1.1 200 OK\x0d\x0a" . $headers; } - $message =~ s/\x0D?\x0A[\x09\x20]+/\x20/gs; + my $response = HTTP::Response->parse($headers); + $response->date( time() ) unless $response->date; - foreach ( split /\x0D?\x0A/, $message ) { + my $message = $response->message; + my $status = $response->header('Status'); - s/[\x09\x20]*$//; - - if ( /^($HTTP_Token+)[\x09\x20]*:[\x09\x20]*([\x20-\xFF]+)$/o ) { - $response->headers->push_header( $1 => $2 ); - } - else { - # XXX what should we do on bad headers? - } + if ( $message && $message =~ /^(.+)\x0d$/ ) { + $response->message($1); } - my $status = $response->header('Status'); + if ( $status && $status =~ /^(\d\d\d)\s?(.+)?$/ ) { - if ( $status && $status =~ /^(\d\d\d)[\x09\x20]+([\x20-\xFF]+)$/ ) { - $response->code($1); - $response->message($2); - } + my $code = $1; + my $message = $2 || HTTP::Status::status_message($code); - if ( !$response->date ) { - $response->date(time()); + $response->code($code); + $response->message($message); } + + my $length = ( stat( $self->stdout ) )[7] - tell( $self->stdout ); - if ( $params{headers_only} ) { - - if ( $params{sync} ) { - - my $position = tell( $self->stdout ) - or croak("Couldn't get file position from stdout filehandle: '$!'"); + if ( $response->code == 500 && !$length ) { - sysseek( $self->stdout, $position, SEEK_SET ) - or croak("Couldn't seek stdout filehandle: '$!'"); - } + $response->content( $response->error_as_HTML ); + $response->content_type('text/html'); return $response; } - my $content = undef; - my $content_length = 0; + if ($callback) { - while () { + my $handle = $self->stdout; - my $r = read( $self->stdout, $content, 65536, $content_length ); + $response->content( sub { - if ( defined $r ) { - - if ( $r == 0 ) { - last; - } - else { - $content_length += $r; + if ( $handle->read( my $buffer, 4096 ) ) { + return $buffer; } - } - else { - croak("Couldn't read response content from stdin filehandle: '$!'"); - } + + return undef; + }); } + else { - if ( $content_length ) { + my $length = 0; - $response->content_ref(\$content); + while ( $self->stdout->read( my $buffer, 4096 ) ) { + $length += length($buffer); + $response->add_content($buffer); + } - if ( !$response->content_length ) { - $response->content_length($content_length); + if ( $length && !$response->content_length ) { + $response->content_length($length); } } @@ -493,111 +222,49 @@ sub response { sub restore { my $self = shift; - if ( !$self->should_restore ) { - croak( 'An attempt was made to restore environment variables and ' - . 'standard filehandles which has not been saved.' ); - } - - if ( !$self->is_setup ) { - croak( 'An attempt was made to restore environment variables and ' - . 'standard filehandles which has not been setup.' ); - } - - if ( $self->is_restored ) { - croak( 'An attempt was made to restore environment variables and ' - . 'standard filehandles which has already been restored.' ); - } - { no warnings 'uninitialized'; - %ENV = %{ $self->{restore}->{environment} }; + %ENV = %{ $self->{restore}->{enviroment} }; } - if ( $self->has_stdin ) { + open( STDIN, '<&', $self->{restore}->{stdin} ) + or croak("Can't restore stdin: $!"); - my $stdin = $self->{restore}->{stdin}; + sysseek( $self->stdin, 0, SEEK_SET ) + or croak("Can't seek stdin: $!"); - if ( $self->should_dup ) { + if ( $self->{restore}->{stdout} ) { - STDIN->fdopen( fileno($stdin), '<' ) - or croak("Couldn't restore STDIN: '$!'"); - } - else { + STDOUT->flush + or croak("Can't flush stdout: $!"); - my $stdin_ref = $self->{restore}->{stdin_ref}; - *$stdin_ref = $stdin; - } + open( STDOUT, '>&', $self->{restore}->{stdout} ) + or croak("Can't restore stdout: $!"); - if ( $self->should_rewind ) { - - seek( $self->stdin, 0, SEEK_SET ) - or croak("Couldn't rewind stdin filehandle: '$!'"); - } + sysseek( $self->stdout, 0, SEEK_SET ) + or croak("Can't seek stdout: $!"); } - if ( $self->has_stdout ) { - - my $stdout = $self->{restore}->{stdout}; - - if ( $self->should_dup ) { - - STDOUT->flush - or croak("Couldn't flush STDOUT: '$!'"); - - STDOUT->fdopen( fileno($stdout), '>' ) - or croak("Couldn't restore STDOUT: '$!'"); - } - else { + if ( $self->{restore}->{stderr} ) { - my $stdout_ref = $self->{restore}->{stdout_ref}; - *$stdout_ref = $stdout; - } + STDERR->flush + or croak("Can't flush stderr: $!"); - if ( $self->should_rewind ) { + open( STDERR, '>&', $self->{restore}->{stderr} ) + or croak("Can't restore stderr: $!"); - seek( $self->stdout, 0, SEEK_SET ) - or croak("Couldn't rewind stdout filehandle: '$!'"); - } + sysseek( $self->stderr, 0, SEEK_SET ) + or croak("Can't seek stderr: $!"); } - if ( $self->has_stderr ) { - - my $stderr = $self->{restore}->{stderr}; - - if ( $self->should_dup ) { - - STDERR->flush - or croak("Couldn't flush STDERR: '$!'"); - - STDERR->fdopen( fileno($stderr), '>' ) - or croak("Couldn't restore STDERR: '$!'"); - } - else { - - my $stderr_ref = $self->{restore}->{stderr_ref}; - *$stderr_ref = $stderr; - } - - if ( $self->should_rewind ) { - - seek( $self->stderr, 0, SEEK_SET ) - or croak("Couldn't rewind stderr filehandle: '$!'"); - } - } - - $self->{restore} = {}; - - $self->is_restored(1); + $self->{restored}++; return $self; } sub DESTROY { my $self = shift; - - if ( $self->should_restore && $self->is_setup && !$self->is_restored ) { - $self->restore; - } + $self->restore if $self->{setuped} && !$self->{restored}; } 1; @@ -606,204 +273,87 @@ __END__ =head1 NAME -HTTP::Request::AsCGI - Setup a Common Gateway Interface environment from a HTTP::Request +HTTP::Request::AsCGI - Setup a CGI enviroment from a HTTP::Request =head1 SYNOPSIS use CGI; use HTTP::Request; use HTTP::Request::AsCGI; - + my $request = HTTP::Request->new( GET => 'http://www.host.com/' ); my $stdout; - + { my $c = HTTP::Request::AsCGI->new($request)->setup; my $q = CGI->new; - + print $q->header, $q->start_html('Hello World'), $q->h1('Hello World'), $q->end_html; - + $stdout = $c->stdout; - - # environment and descriptors is automatically restored + + # enviroment and descriptors will automatically be restored # when $c is destructed. } - + while ( my $line = $stdout->getline ) { print $line; } - + =head1 DESCRIPTION -Provides a convinient way of setting up an CGI environment from a HTTP::Request. +Provides a convinient way of setting up an CGI enviroment from a HTTP::Request. =head1 METHODS -=over 4 - -=item * new - -Constructor, this method takes a hash of parameters. The following parameters are -valid: - -=over 8 - -=item * request - - request => HTTP::Request->new( GET => 'http://www.host.com/' ) - -=item * stdin - -A filehandle to be used as standard input, defaults to a temporary filehandle. -If C is C, standard input will be left as is. - - stdin => IO::File->new_tmpfile - stdin => IO::String->new - stdin => $fh - stdin => undef - -=item * stdout - -A filehandle to be used as standard output, defaults to a temporary filehandle. -If C is C, standard output will be left as is. - - stdout => IO::File->new_tmpfile - stdout => IO::String->new - stdout => $fh - stdout => undef +=over 4 -=item * stderr +=item new ( $request [, key => value ] ) -A filehandle to be used as standard error, defaults to C. If C is -C, standard error will be left as is. +Contructor, first argument must be a instance of HTTP::Request +followed by optional pairs of environment key and value. - stderr => IO::File->new_tmpfile - stderr => IO::String->new - stderr => $fh - stderr => undef +=item enviroment -=item * environment +Returns a hashref containing the environment that will be used in setup. +Changing the hashref after setup has been called will have no effect. -A C of additional environment variables to be used in CGI. -C doesn't autmatically merge C<%ENV>, it has to be -explicitly given if that is desired. Environment variables given in this -C isn't overridden by C. +=item setup - environment => \%ENV - environment => { PATH => '/bin:/usr/bin', SERVER_SOFTWARE => 'Apache/1.3' } +Setups the environment and descriptors. -Following standard meta-variables (in addition to protocol-specific) is setup: +=item restore - AUTH_TYPE - CONTENT_LENGTH - CONTENT_TYPE - GATEWAY_INTERFACE - PATH_INFO - SCRIPT_NAME - SERVER_NAME - SERVER_PORT - SERVER_PROTOCOL - SERVER_SOFTWARE - REMOTE_ADDR - REMOTE_HOST - REMOTE_USER - REQUEST_METHOD - QUERY_STRING +Restores the enviroment and descriptors. Can only be called after setup. -Following non-standard but common meta-variables is setup: +=item request - HTTPS - REMOTE_PORT - REQUEST_URI +Returns the request given to constructor. -Following meta-variables is B setup but B be provided in CGI: +=item response - PATH_TRANSLATED +Returns a HTTP::Response. Can only be called after restore. -Following meta-variables is B setup but common in CGI: +=item stdin - DOCUMENT_ROOT - SCRIPT_FILENAME - SERVER_ROOT +Accessor for handle that will be used for STDIN, must be a real seekable +handle with an file descriptor. Defaults to a tempoary IO::File instance. -=item * dup +=item stdout -Boolean to indicate whether to C standard filehandle or to assign the -typeglob representing the standard filehandle. Defaults to C. +Accessor for handle that will be used for STDOUT, must be a real seekable +handle with an file descriptor. Defaults to a tempoary IO::File instance. - dup => 0 - dup => 1 +=item stderr -=item * restore - -Boolean to indicate whether or not to restore environment variables and standard -filehandles. Defaults to C. - - restore => 0 - restore => 1 - -If C standard filehandles and environment variables will be saved duiring -C for later use in C. - -=item * rewind - -Boolean to indicate whether or not to rewind standard filehandles. Defaults -to C. - - rewind => 0 - rewind => 1 - -=item * content - -Boolean to indicate whether or not to request content should be written to -C filehandle when C is invoked. Defaults to C. - - content => 0 - content => 1 +Accessor for handle that will be used for STDERR, must be a real seekable +handle with an file descriptor. =back -=item * setup - -Attempts to setup standard filehandles and environment variables. - -=item * restore - -Attempts to restore standard filehandles and environment variables. - -=item * response - -Attempts to parse C filehandle into a L. - -=item * request - -Accessor for L that was given to constructor. - -=item * environment - -Accessor for environment variables to be used in C. - -=item * stdin - -Accessor/Mutator for standard input filehandle. - -=item * stdout - -Accessor/Mutator for standard output filehandle. - -=item * stderr - -Accessor/Mutator for standard error filehandle. - -=back - -=head1 DEPRECATED - -XXX Constructor - =head1 SEE ALSO =over 4 @@ -826,7 +376,7 @@ Christian Hansen, C =head1 LICENSE -This library is free software. You can redistribute it and/or modify +This library is free software. You can redistribute it and/or modify it under the same terms as perl itself. =cut diff --git a/t/01use.t b/t/01use.t index fa63202..5c9fb0f 100644 --- a/t/01use.t +++ b/t/01use.t @@ -1,6 +1,6 @@ #!perl -use Test::More tests => 1; +use Test::More 'no_plan'; use strict; use warnings; diff --git a/t/02pod.t b/t/02pod.t deleted file mode 100644 index 1647794..0000000 --- a/t/02pod.t +++ /dev/null @@ -1,7 +0,0 @@ -use Test::More; - -eval "use Test::Pod 1.14"; -plan skip_all => 'Test::Pod 1.14 required' if $@; -plan skip_all => 'set TEST_POD to enable this test' unless $ENV{TEST_POD}; - -all_pod_files_ok(); diff --git a/t/04io.t b/t/04io.t index 3b73013..029c5a7 100644 --- a/t/04io.t +++ b/t/04io.t @@ -14,11 +14,8 @@ $r->content('STDIN'); $r->content_length(5); $r->content_type('text/plain'); -my $c = HTTP::Request::AsCGI->new( - request => $r, - stderr => IO::File->new_tmpfile -); - +my $c = HTTP::Request::AsCGI->new($r); +$c->stderr(IO::File->new_tmpfile); $c->setup; print STDOUT 'STDOUT'; diff --git a/t/04ioscalar.t b/t/04ioscalar.t deleted file mode 100644 index 345f315..0000000 --- a/t/04ioscalar.t +++ /dev/null @@ -1,47 +0,0 @@ -#!perl - -use Test::More tests => 3; - -{ - eval "use PerlIO::scalar"; - plan skip_all => 'PerlIO::scalar required' if $@; -} - -use strict; -use warnings; - -use HTTP::Request; -use HTTP::Request::AsCGI; - -my $r = HTTP::Request->new( POST => 'http://www.host.com/'); -$r->content('STDIN'); -$r->content_length(5); -$r->content_type('text/plain'); - -open( my $stdin, ' +<', \( my $stdin_scalar ) ) - or die qq/Couldn't open a new PerlIO::scalar/; - -open( my $stdout, '+>', \( my $stdout_scalar ) ) - or die qq/Couldn't open a new PerlIO::scalar/; - -open( my $stderr, '+>', \( my $stderr_scalar ) ) - or die qq/Couldn't open a new PerlIO::scalar/; - -my $c = HTTP::Request::AsCGI->new( - request => $r, - dup => 0, - stdin => $stdin, - stdout => $stdout, - stderr => $stderr -); - -$c->setup; - -print STDOUT 'STDOUT'; -print STDERR 'STDERR'; - -$c->restore; - -is( $c->stdin->getline, 'STDIN', 'STDIN' ); -is( $c->stdout->getline, 'STDOUT', 'STDOUT' ); -is( $c->stderr->getline, 'STDERR', 'STDERR' ); diff --git a/t/04iostring.t b/t/04iostring.t deleted file mode 100644 index 23810e1..0000000 --- a/t/04iostring.t +++ /dev/null @@ -1,38 +0,0 @@ -#!perl - -use Test::More tests => 3; - -{ - eval "use IO::String 1.07"; - plan skip_all => 'IO::String 1.07 required' if $@; -} - -use strict; -use warnings; - -use HTTP::Request; -use HTTP::Request::AsCGI; - -my $r = HTTP::Request->new( POST => 'http://www.host.com/'); -$r->content('STDIN'); -$r->content_length(5); -$r->content_type('text/plain'); - -my $c = HTTP::Request::AsCGI->new( - request => $r, - dup => 0, - stdin => IO::String->new, - stdout => IO::String->new, - stderr => IO::String->new -); - -$c->setup; - -print STDOUT 'STDOUT'; -print STDERR 'STDERR'; - -$c->restore; - -is( $c->stdin->getline, 'STDIN', 'STDIN' ); -is( $c->stdout->getline, 'STDOUT', 'STDOUT' ); -is( $c->stderr->getline, 'STDERR', 'STDERR' ); diff --git a/t/05env.t b/t/05env.t index bbb7125..209d61e 100644 --- a/t/05env.t +++ b/t/05env.t @@ -1,6 +1,6 @@ #!perl -use Test::More tests => 12; +use Test::More tests => 10; use strict; use warnings; @@ -9,13 +9,9 @@ use HTTP::Request; use HTTP::Request::AsCGI; my $r = HTTP::Request->new( GET => 'http://www.host.com/cgi-bin/script.cgi/my/path/?a=1&b=2', [ 'X-Test' => 'Test' ] ); - $r->authorization_basic( 'chansen', 'xxx' ); - -my $c = HTTP::Request::AsCGI->new( - environment => { SCRIPT_NAME => '/cgi-bin/script.cgi' }, - request => $r, - stdout => undef -); +my %e = ( SCRIPT_NAME => '/cgi-bin/script.cgi' ); +my $c = HTTP::Request::AsCGI->new( $r, %e ); +$c->stdout(undef); $c->setup; @@ -24,8 +20,6 @@ is( $ENV{HTTP_HOST}, 'www.host.com:80', 'HTTP_HOST' ); is( $ENV{HTTP_X_TEST}, 'Test', 'HTTP_X_TEST' ); is( $ENV{PATH_INFO}, '/my/path/', 'PATH_INFO' ); is( $ENV{QUERY_STRING}, 'a=1&b=2', 'QUERY_STRING' ); -is( $ENV{AUTH_TYPE}, 'Basic', 'AUTH_TYPE' ); -is( $ENV{REMOTE_USER}, 'chansen', 'REMOTE_USER' ); is( $ENV{SCRIPT_NAME}, '/cgi-bin/script.cgi', 'SCRIPT_NAME' ); is( $ENV{REQUEST_METHOD}, 'GET', 'REQUEST_METHOD' ); is( $ENV{SERVER_NAME}, 'www.host.com', 'SERVER_NAME' ); diff --git a/t/06response.t b/t/06response.t index 68e3ba2..f3f9891 100644 --- a/t/06response.t +++ b/t/06response.t @@ -13,7 +13,7 @@ my $response; { my $r = HTTP::Request->new( GET => 'http://www.host.com/' ); - my $c = HTTP::Request::AsCGI->new( request => $r ); + my $c = HTTP::Request::AsCGI->new($r); $c->setup; diff --git a/t/07forking.t b/t/07forking.t index 16b949b..c4f0463 100644 --- a/t/07forking.t +++ b/t/07forking.t @@ -10,7 +10,7 @@ use HTTP::Request::AsCGI; use Test::More; unless ( $Config{d_fork} ) { - plan skip_all => 'This test requires a platform that supports fork()'; + plan skip_all => 'This test requires a plattform that supports fork()'; } plan tests => 8; @@ -19,7 +19,7 @@ my $response; { my $r = HTTP::Request->new( GET => 'http://www.host.com/' ); - my $c = HTTP::Request::AsCGI->new( request => $r ); + my $c = HTTP::Request::AsCGI->new($r); my $kid = fork(); diff --git a/t/08error.t b/t/08error.t index d611bb4..f117014 100644 --- a/t/08error.t +++ b/t/08error.t @@ -13,7 +13,7 @@ my $response; { my $r = HTTP::Request->new( GET => 'http://www.host.com/' ); - my $c = HTTP::Request::AsCGI->new( request => $r ); + my $c = HTTP::Request::AsCGI->new($r); $c->setup; @@ -29,10 +29,10 @@ ok( length($response->content) > 0, 'Response Content' ); { my $r = HTTP::Request->new( GET => 'http://www.host.com/' ); - my $c = HTTP::Request::AsCGI->new( request => $r ); + my $c = HTTP::Request::AsCGI->new($r); $c->setup; - + print "Content-Type: text/plain\n"; print "Status: 500 Borked\n"; print "\n"; diff --git a/t/deprecated/04io.t b/t/deprecated/04io.t deleted file mode 100644 index 029c5a7..0000000 --- a/t/deprecated/04io.t +++ /dev/null @@ -1,28 +0,0 @@ -#!perl - -use Test::More tests => 3; - -use strict; -use warnings; - -use IO::File; -use HTTP::Request; -use HTTP::Request::AsCGI; - -my $r = HTTP::Request->new( POST => 'http://www.host.com/'); -$r->content('STDIN'); -$r->content_length(5); -$r->content_type('text/plain'); - -my $c = HTTP::Request::AsCGI->new($r); -$c->stderr(IO::File->new_tmpfile); -$c->setup; - -print STDOUT 'STDOUT'; -print STDERR 'STDERR'; - -$c->restore; - -is( $c->stdin->getline, 'STDIN', 'STDIN' ); -is( $c->stdout->getline, 'STDOUT', 'STDOUT' ); -is( $c->stderr->getline, 'STDERR', 'STDERR' ); diff --git a/t/deprecated/05env.t b/t/deprecated/05env.t deleted file mode 100644 index 18ac328..0000000 --- a/t/deprecated/05env.t +++ /dev/null @@ -1,33 +0,0 @@ -#!perl - -use Test::More tests => 12; - -use strict; -use warnings; - -use HTTP::Request; -use HTTP::Request::AsCGI; - -my $r = HTTP::Request->new( GET => 'http://www.host.com/cgi-bin/script.cgi/my/path/?a=1&b=2', [ 'X-Test' => 'Test' ] ); - $r->authorization_basic( 'chansen', 'xxx' ); -my %e = ( SCRIPT_NAME => '/cgi-bin/script.cgi' ); -my $c = HTTP::Request::AsCGI->new( $r, %e ); - -$c->stdout(undef); -$c->setup; - -is( $ENV{GATEWAY_INTERFACE}, 'CGI/1.1', 'GATEWAY_INTERFACE' ); -is( $ENV{HTTP_HOST}, 'www.host.com:80', 'HTTP_HOST' ); -is( $ENV{HTTP_X_TEST}, 'Test', 'HTTP_X_TEST' ); -is( $ENV{PATH_INFO}, '/my/path/', 'PATH_INFO' ); -is( $ENV{QUERY_STRING}, 'a=1&b=2', 'QUERY_STRING' ); -is( $ENV{AUTH_TYPE}, 'Basic', 'AUTH_TYPE' ); -is( $ENV{REMOTE_USER}, 'chansen', 'REMOTE_USER' ); -is( $ENV{SCRIPT_NAME}, '/cgi-bin/script.cgi', 'SCRIPT_NAME' ); -is( $ENV{REQUEST_METHOD}, 'GET', 'REQUEST_METHOD' ); -is( $ENV{SERVER_NAME}, 'www.host.com', 'SERVER_NAME' ); -is( $ENV{SERVER_PORT}, '80', 'SERVER_PORT' ); - -$c->restore; - -is( $ENV{GATEWAY_INTERFACE}, undef, 'No CGI env after restore' ); diff --git a/t/deprecated/06response.t b/t/deprecated/06response.t deleted file mode 100644 index f3f9891..0000000 --- a/t/deprecated/06response.t +++ /dev/null @@ -1,39 +0,0 @@ -#!perl - -use Test::More tests => 9; - -use strict; -use warnings; - -use IO::File; -use HTTP::Request; -use HTTP::Request::AsCGI; - -my $response; - -{ - my $r = HTTP::Request->new( GET => 'http://www.host.com/' ); - my $c = HTTP::Request::AsCGI->new($r); - - $c->setup; - - print "Content-Type: text/plain\n"; - print "Status: 200 Yay\n"; - print "Date: Thu, 19 Jan 2006 14:08:18 GMT\n"; - print "X-Field: 1\n"; - print "X-Field: 2\n"; - print "\n"; - print "Hello!"; - - $response = $c->restore->response; -} - -isa_ok( $response, 'HTTP::Response' ); -is( $response->code, 200, 'Response Code' ); -is( $response->message, 'Yay', 'Response Message' ); -is( $response->protocol, 'HTTP/1.1', 'Response Protocol' ); -is( $response->content, 'Hello!', 'Response Content' ); -is( $response->content_length, 6, 'Response Content-Length' ); -is( $response->content_type, 'text/plain', 'Response Content-Type' ); -is( $response->header('Date'), 'Thu, 19 Jan 2006 14:08:18 GMT', 'Response Date' ); -is_deeply( [ $response->header('X-Field') ], [ 1, 2 ], 'Response Header X-Field' ); diff --git a/t/deprecated/07forking.t b/t/deprecated/07forking.t deleted file mode 100644 index 1bccc30..0000000 --- a/t/deprecated/07forking.t +++ /dev/null @@ -1,59 +0,0 @@ -#!perl - -use strict; -use warnings; - -use Config; -use IO::File; -use HTTP::Request; -use HTTP::Request::AsCGI; -use Test::More; - -unless ( $Config{d_fork} ) { - plan skip_all => 'This test requires a platform that supports fork()'; -} - -plan tests => 8; - -my $response; - -{ - my $r = HTTP::Request->new( GET => 'http://www.host.com/' ); - my $c = HTTP::Request::AsCGI->new($r); - - my $kid = fork(); - - unless ( defined $kid ) { - die("Can't fork() kid: $!"); - } - - unless ( $kid ) { - - $c->setup; - - print "HTTP/1.0 200 OK\n"; - print "Content-Type: text/plain\n"; - print "Status: 200\n"; - print "X-Field: 1\n"; - print "X-Field: 2\n"; - print "\n"; - print "Hello!"; - - $c->restore; - - exit(0); - } - - waitpid( $kid, 0 ); - - $response = $c->response; -} - -isa_ok( $response, 'HTTP::Response' ); -is( $response->code, 200, 'Response Code' ); -is( $response->message, 'OK', 'Response Message' ); -is( $response->protocol, 'HTTP/1.0', 'Response Protocol' ); -is( $response->content, 'Hello!', 'Response Content' ); -is( $response->content_length, 6, 'Response Content-Length' ); -is( $response->content_type, 'text/plain', 'Response Content-Type' ); -is_deeply( [ $response->header('X-Field') ], [ 1, 2 ], 'Response Header X-Field' ); diff --git a/t/deprecated/08error.t b/t/deprecated/08error.t deleted file mode 100644 index f117014..0000000 --- a/t/deprecated/08error.t +++ /dev/null @@ -1,49 +0,0 @@ -#!perl - -use Test::More tests => 12; - -use strict; -use warnings; - -use IO::File; -use HTTP::Request; -use HTTP::Request::AsCGI; - -my $response; - -{ - my $r = HTTP::Request->new( GET => 'http://www.host.com/' ); - my $c = HTTP::Request::AsCGI->new($r); - - $c->setup; - - $response = $c->restore->response; -} - -isa_ok( $response, 'HTTP::Response' ); -is( $response->code, 500, 'Response Code' ); -is( $response->message, 'Internal Server Error', 'Response Message' ); -is( $response->protocol, 'HTTP/1.1', 'Response Protocol' ); -is( $response->content_type, 'text/html', 'Response Content-Type' ); -ok( length($response->content) > 0, 'Response Content' ); - -{ - my $r = HTTP::Request->new( GET => 'http://www.host.com/' ); - my $c = HTTP::Request::AsCGI->new($r); - - $c->setup; - - print "Content-Type: text/plain\n"; - print "Status: 500 Borked\n"; - print "\n"; - print "Borked!"; - - $response = $c->restore->response; -} - -isa_ok( $response, 'HTTP::Response' ); -is( $response->code, 500, 'Response Code' ); -is( $response->message, 'Borked', 'Response Message' ); -is( $response->protocol, 'HTTP/1.1', 'Response Protocol' ); -is( $response->content_type, 'text/plain', 'Response Content-Type' ); -is( $response->content, 'Borked!', 'Response Content' );