1 package HTTP::Request::AsCGI;
6 use base 'Class::Accessor::Fast';
11 __PACKAGE__->mk_accessors(qw[ enviroment request stdin stdout stderr ]);
23 stdin => IO::File->new_tmpfile,
24 stdout => IO::File->new_tmpfile,
25 stderr => IO::File->new_tmpfile
28 $self->{enviroment} = {
29 GATEWAY_INTERFACE => 'CGI/1.1',
30 HTTP_HOST => $request->uri->host_port,
31 PATH_INFO => $request->uri->path,
32 QUERY_STRING => $request->uri->query || '',
34 SERVER_NAME => $request->uri->host,
35 SERVER_PORT => $request->uri->port,
36 SERVER_PROTOCOL => $request->protocol || 'HTTP/1.1',
37 SERVER_SOFTWARE => __PACKAGE__ . "/" . $VERSION,
38 REMOTE_ADDR => '127.0.0.1',
39 REMOTE_HOST => 'localhost',
40 REMOTE_PORT => int( rand(64000) + 1000 ), # not in RFC 3875
41 REQUEST_URI => $request->uri->path || '/', # not in RFC 3875
42 REQUEST_METHOD => $request->method,
46 foreach my $field ( $request->headers->header_field_names ) {
50 $key = 'HTTP_' . $key unless $field =~ /^Content-(Length|Type)$/;
52 unless ( exists $self->{enviroment}->{$key} ) {
53 $self->{enviroment}->{$key} = $request->headers->header($field);
57 return $class->SUPER::new($self);
63 $self->{restore}->{enviroment} = {%ENV};
65 open( $self->{restore}->{stdin}, '>&', STDIN->fileno )
66 or croak("Can't dup stdin: $!");
68 open( STDIN, '<&=', $self->stdin->fileno )
69 or croak("Can't open stdin: $!");
71 binmode( $self->stdin, ':raw' );
72 binmode( STDIN, ':raw' );
74 if ( $self->request->content_length ) {
76 $self->stdin->syswrite( $self->request->content )
77 or croak("Can't write request content to stdin handle: $!");
79 $self->stdin->sysseek( 0, SEEK_SET )
80 or croak("Can't seek stdin handle: $!");
83 if ( $self->stdout ) {
84 open( $self->{restore}->{stdout}, '>&', STDOUT->fileno )
85 or croak("Can't dup stdout: $!");
87 open( STDOUT, '>&=', $self->stdout->fileno )
88 or croak("Can't open stdout: $!");
90 binmode( $self->stdout, ':raw' );
91 binmode( STDOUT, ':raw' );
94 if ( $self->stderr ) {
95 open( $self->{restore}->{stderr}, '>&', STDERR->fileno )
96 or croak("Can't dup stderr: $!");
98 open( STDERR, '>&=', $self->stderr->fileno )
99 or croak("Can't open stderr: $!");
101 binmode( $self->stderr, ':raw' );
102 binmode( STDERR, ':raw' );
106 no warnings 'uninitialized';
107 %ENV = %{ $self->enviroment };
116 my ( $self, $callback ) = @_;
118 return undef unless $self->{setuped};
119 return undef unless $self->{restored};
120 return undef unless $self->{restore}->{stdout};
122 require HTTP::Response;
125 my $position = $self->stdin->tell;
127 $self->stdout->sysseek( 0, SEEK_SET )
128 or croak("Can't seek stdin handle: $!");
130 while ( my $line = $self->stdout->getline ) {
132 last if $line =~ /^\x0d?\x0a$/;
135 unless ( $message =~ /^HTTP/ ) {
136 $message = "HTTP/1.1 200\x0d\x0a" . $message;
139 my $response = HTTP::Response->parse($message);
141 if ( my $code = $response->header('Status') ) {
142 $response->code($code);
145 $response->protocol( $self->request->protocol );
146 $response->headers->date( time() );
149 $response->content( sub {
150 if ( $self->stdout->read( my $buffer, 4096 ) ) {
158 while ( $self->stdout->read( my $buffer, 4096 ) ) {
159 $length += length($buffer);
160 $response->add_content($buffer);
162 $response->content_length($length) unless $response->content_length;
165 $self->stdout->sysseek( $position, SEEK_SET )
166 or croak("Can't seek stdin handle: $!");
174 %ENV = %{ $self->{restore}->{enviroment} };
176 open( STDIN, '>&', $self->{restore}->{stdin} )
177 or croak("Can't restore stdin: $!");
179 $self->stdin->sysseek( 0, SEEK_SET )
180 or croak("Can't seek stdin: $!");
182 if ( $self->{restore}->{stdout} ) {
183 open( STDOUT, '>&', $self->{restore}->{stdout} )
184 or croak("Can't restore stdout: $!");
186 $self->stdout->sysseek( 0, SEEK_SET )
187 or croak("Can't seek stdout: $!");
190 if ( $self->{restore}->{stderr} ) {
191 open( STDERR, '>&', $self->{restore}->{stderr} )
192 or croak("Can't restore stderr: $!");
194 $self->stderr->sysseek( 0, SEEK_SET )
195 or croak("Can't seek stderr: $!");
205 $self->restore if $self->{setuped} && !$self->{restored};
214 HTTP::Request::AsCGI - Setup a CGI enviroment from a HTTP::Request
220 use HTTP::Request::AsCGI;
222 my $request = HTTP::Request->new( GET => 'http://www.host.com/' );
226 my $c = HTTP::Request::AsCGI->new($request)->setup;
230 $q->start_html('Hello World'),
231 $q->h1('Hello World'),
234 $stdout = $c->stdout;
236 # enviroment and descriptors will automatically be restored when $c is destructed.
239 while ( my $line = $stdout->getline ) {
273 Christian Hansen, C<ch@ngmedia.com>
277 This library is free software. You can redistribute it and/or modify
278 it under the same terms as perl itself.