9d062a2b33fd572913d07db7109cf719ff9d61b2
[catagits/HTTP-Request-AsCGI.git] / lib / HTTP / Request / AsCGI.pm
1 package HTTP::Request::AsCGI;
2
3 use strict;
4 use warnings;
5 use base 'Class::Accessor::Fast';
6
7 use Carp;
8 use IO::Handle;
9 use File::Temp;
10
11 __PACKAGE__->mk_accessors( qw[ enviroment request stdin stdout stderr ] );
12
13 our $VERSION = 0.1;
14
15 sub new {
16     my $class   = shift;
17     my $request = shift;
18
19     my $self = {
20         request  => $request,
21         restored => 0,
22         stdin    => File::Temp->new,
23         stdout   => File::Temp->new,
24         stderr   => File::Temp->new
25     };
26
27     $self->{enviroment} = {
28         GATEWAY_INTERFACE => 'CGI/1.1',
29         HTTP_HOST         => $request->uri->host_port,
30         QUERY_STRING      => $request->uri->query || '',
31         SCRIPT_NAME       => $request->uri->path || '/',
32         SERVER_NAME       => $request->uri->host,
33         SERVER_PORT       => $request->uri->port,
34         SERVER_PROTOCOL   => $request->protocol || 'HTTP/1.1',
35         SERVER_SOFTWARE   => __PACKAGE__ . "/" . $VERSION,
36         REMOTE_ADDR       => '127.0.0.1',
37         REMOTE_HOST       => 'localhost',
38         REMOTE_PORT       => int( rand(64000) + 1000 ),        # not in RFC 3875
39         REQUEST_URI       => $request->uri->path || '/',       # not in RFC 3875
40         REQUEST_METHOD    => $request->method,
41         @_
42     };
43
44     foreach my $field ( $request->headers->header_field_names ) {
45
46         my $key = uc($field);
47         $key =~ tr/_/-/;
48         $key = 'HTTP_' . $key unless $field =~ /^Content-(Length|Type)$/;
49
50         unless ( exists $self->{enviroment}->{$key} ) {
51             $self->{enviroment}->{$key} = $request->headers->header($field);
52         }
53     }
54
55     return $class->SUPER::new($self);
56 }
57
58 sub setup {
59     my $self = shift;
60
61     open( my $stdin, '>&', STDIN->fileno )
62       or croak("Can't dup stdin: $!");
63
64     open( my $stdout, '>&', STDOUT->fileno )
65       or croak("Can't dup stdout: $!");
66
67     open( my $stderr, '>&', STDERR->fileno )
68       or croak("Can't dup stderr: $!");
69
70     $self->{restore} = {
71         stdin      => $stdin,
72         stdout     => $stdout,
73         stderr     => $stderr,
74         enviroment => {%ENV}
75     };
76
77     if ( $self->request->content_length ) {
78
79         $self->stdin->write( $self->request->content )
80           or croak("Can't write content: $!");
81
82         seek( $self->stdin, 0, 0 )
83           or croak("Can't seek stdin: $!");
84     }
85
86     %ENV = %{ $self->enviroment };
87
88     open( STDIN, '<&=', $self->stdin->fileno )
89       or croak("Can't open stdin: $!");
90
91     open( STDOUT, '>&=', $self->stdout->fileno )
92       or croak("Can't open stdout: $!");
93
94     open( STDERR, '>&=', $self->stderr->fileno )
95       or croak("Can't open stderr: $!");
96
97     return $self;
98 }
99
100 sub restore {
101     my $self = shift;
102
103     %ENV = %{ $self->{restore}->{enviroment} };
104
105     open( STDIN, '>&', $self->{restore}->{stdin} )
106       or croak("Can't restore stdin: $!");
107
108     open( STDOUT, '>&', $self->{restore}->{stdout} )
109       or croak("Can't restore stdout: $!");
110
111     open( STDERR, '>&', $self->{restore}->{stderr} )
112       or croak("Can't restore stderr: $!");
113       
114     $self->{restored}++;
115 }
116
117 sub DESTROY {
118     my $self = shift;
119     $self->restore unless $self->{restored};
120 }
121
122 1;
123
124 __END__
125
126 =head1 NAME
127
128 HTTP::Request::AsCGI - Create a CGI enviroment from a HTTP::Request
129
130 =head1 SYNOPSIS
131
132 =head1 DESCRIPTION
133
134 =head1 METHODS
135
136 =over 4 
137
138 =item new
139
140 =item setup
141
142 =item restore
143
144 =item request
145
146 =item stdin
147
148 =item stdout
149
150 =item stderr
151
152 =back
153
154 =head1 BUGS
155
156 =head1 AUTHOR
157
158 Christian Hansen, C<ch@ngmedia.com>
159
160 =head1 LICENSE
161
162 This library is free software. You can redistribute it and/or modify 
163 it under the same terms as perl itself.
164
165 =cut