added connection stuff
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Engine / CGI.pm
1 package Catalyst::Engine::CGI;
2
3 use strict;
4 use base 'Catalyst::Engine';
5 use URI;
6
7 require CGI::Simple;
8 require CGI::Cookie;
9
10 $CGI::Simple::POST_MAX        = 1048576;
11 $CGI::Simple::DISABLE_UPLOADS = 0;
12
13 __PACKAGE__->mk_accessors('cgi');
14
15 =head1 NAME
16
17 Catalyst::Engine::CGI - The CGI Engine
18
19 =head1 SYNOPSIS
20
21 A script using the Catalyst::Engine::CGI module might look like:
22
23     #!/usr/bin/perl -w
24
25     use strict;
26     use lib '/path/to/MyApp/lib';
27     use MyApp;
28
29     MyApp->run;
30
31 The application module (C<MyApp>) would use C<Catalyst>, which loads the
32 appropriate engine module.
33
34 =head1 DESCRIPTION
35
36 This is the Catalyst engine specialized for the CGI environment (using the
37 C<CGI::Simple> and C<CGI::Cookie> modules).  Normally Catalyst will select the
38 appropriate engine according to the environment that it detects, however you
39 can force Catalyst to use the CGI engine by specifying the following in your
40 application module:
41
42     use Catalyst qw(-Engine=CGI);
43
44 Catalyst::Engine::CGI generates a full set of HTTP headers, which means that
45 applications using the engine must be be configured as "Non-parsed Headers"
46 scripts (at least when running under Apache).  To configure this under Apache
47 name the starting with C<nph->.
48
49 The performance of this way of using Catalyst is not expected to be
50 useful in production applications, but it may be helpful for development.
51
52 =head1 METHODS
53
54 =over 4
55
56 =item $c->run
57
58 To be called from a CGI script to start the Catalyst application.
59
60 =item $c->cgi
61
62 This config parameter contains the C<CGI::Simple> object.
63
64 =back
65
66 =head1 OVERLOADED METHODS
67
68 This class overloads some methods from C<Catalyst>.
69
70 =over 4
71
72 =item $c->finalize_headers
73
74 =cut
75
76 sub finalize_headers {
77     my $c = shift;
78     my %headers = ( -nph => 1 );
79     $headers{-status} = $c->response->status if $c->response->status;
80     for my $name ( $c->response->headers->header_field_names ) {
81         $headers{"-$name"} = $c->response->headers->header($name);
82     }
83     my @cookies;
84     while ( my ( $name, $cookie ) = each %{ $c->response->cookies } ) {
85         push @cookies, $c->cgi->cookie(
86             -name    => $name,
87             -value   => $cookie->{value},
88             -expires => $cookie->{expires},
89             -domain  => $cookie->{domain},
90             -path    => $cookie->{path},
91             -secure  => $cookie->{secure} || 0
92         );
93     }
94     $headers{-cookie} = \@cookies if @cookies;
95     print $c->cgi->header(%headers);
96 }
97
98 =item $c->finalize_output
99
100 Prints the response output to STDOUT.
101
102 =cut
103
104 sub finalize_output {
105     my $c = shift;
106     print $c->response->output;
107 }
108
109 =item $c->prepare_connection
110
111 =cut
112
113 sub prepare_connection {
114     my $c = shift;
115     $c->req->hostname( $c->cgi->remote_host );
116     $c->req->address( $c->cgi->remote_addr );
117 }
118
119 =item $c->prepare_cookies
120
121 Sets up cookies.
122
123 =cut
124
125 sub prepare_cookies { shift->req->cookies( { CGI::Cookie->fetch } ) }
126
127 =item $c->prepare_headers
128
129 =cut
130
131 sub prepare_headers {
132     my $c = shift;
133     $c->req->method( $c->cgi->request_method );
134     for my $header ( $c->cgi->http ) {
135         ( my $field = $header ) =~ s/^HTTPS?_//;
136         $c->req->headers->header( $field => $c->cgi->http($header) );
137     }
138 }
139
140 =item $c->prepare_parameters
141
142 =cut
143
144 sub prepare_parameters {
145     my $c    = shift;
146     my %vars = $c->cgi->Vars;
147     while ( my ( $key, $value ) = each %vars ) {
148         my @values = split "\0", $value;
149         $vars{$key} = @values <= 1 ? $values[0] : \@values;
150     }
151     $c->req->parameters( {%vars} );
152 }
153
154 =item $c->prepare_path
155
156 =cut
157
158 sub prepare_path {
159     my $c = shift;
160     $c->req->path( $c->cgi->url( -absolute => 1, -path_info => 1 ) );
161     my $loc = $c->cgi->url( -absolute => 1 );
162     no warnings 'uninitialized';
163     $c->req->{path} =~ s/^($loc)?\///;
164     $c->req->{path} .= '/' if $c->req->path eq $loc;
165     my $base = $c->cgi->url;
166     if ( $ENV{CATALYST_TEST} ) {
167         my $script = $c->cgi->script_name;
168         $base =~ s/$script$//i;
169     }
170     $base = URI->new($base);
171     $base->path('/') if ( $ENV{CATALYST_TEST} || !$base->path );
172     $c->req->base( $base->as_string );
173 }
174
175 =item $c->prepare_request
176
177 =cut
178
179 sub prepare_request { shift->cgi( CGI::Simple->new ) }
180
181 =item $c->prepare_uploads
182
183 =cut
184
185 sub prepare_uploads {
186     my $c = shift;
187     for my $name ( $c->cgi->upload ) {
188         $c->req->uploads->{$name} = {
189             fh   => $c->cgi->upload($name),
190             size => $c->cgi->upload_info( $name, 'size' ),
191             type => $c->cgi->upload_info( $name, 'mime' )
192         };
193     }
194 }
195
196 sub run { shift->handler }
197
198 =back
199
200 =head1 SEE ALSO
201
202 L<Catalyst>.
203
204 =head1 AUTHOR
205
206 Sebastian Riedel, C<sri@cpan.org>
207
208 =head1 COPYRIGHT
209
210 This program is free software, you can redistribute it and/or modify it under
211 the same terms as Perl itself.
212
213 =cut
214
215 1;