- Improved: Params handling with MP engines
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Engine / CGI.pm
CommitLineData
fc7ec1d9 1package Catalyst::Engine::CGI;
2
3use strict;
4use base 'Catalyst::Engine';
e7c0c583 5
6use CGI;
fc7ec1d9 7use URI;
399ed680 8use URI::http;
fc7ec1d9 9
fc7ec1d9 10__PACKAGE__->mk_accessors('cgi');
11
12=head1 NAME
13
14Catalyst::Engine::CGI - The CGI Engine
15
16=head1 SYNOPSIS
17
23f9d934 18A script using the Catalyst::Engine::CGI module might look like:
19
9a33da6a 20 #!/usr/bin/perl -w
21
22 use strict;
23 use lib '/path/to/MyApp/lib';
24 use MyApp;
25
26 MyApp->run;
27
23f9d934 28The application module (C<MyApp>) would use C<Catalyst>, which loads the
29appropriate engine module.
fc7ec1d9 30
31=head1 DESCRIPTION
32
23f9d934 33This is the Catalyst engine specialized for the CGI environment (using the
e7c0c583 34C<CGI> and C<CGI::Cookie> modules). Normally Catalyst will select the
23f9d934 35appropriate engine according to the environment that it detects, however you
36can force Catalyst to use the CGI engine by specifying the following in your
37application module:
38
39 use Catalyst qw(-Engine=CGI);
fc7ec1d9 40
9a33da6a 41The performance of this way of using Catalyst is not expected to be
42useful in production applications, but it may be helpful for development.
43
23f9d934 44=head1 METHODS
fc7ec1d9 45
23f9d934 46=over 4
47
23f9d934 48=item $c->cgi
fc7ec1d9 49
e7c0c583 50This config parameter contains the C<CGI> object.
fc7ec1d9 51
23f9d934 52=back
53
54=head1 OVERLOADED METHODS
fc7ec1d9 55
45374ac6 56This class overloads some methods from C<Catalyst::Engine>.
fc7ec1d9 57
23f9d934 58=over 4
59
06e1b616 60=item $c->finalize_body
61
62Prints the response output to STDOUT.
63
64=cut
65
66sub finalize_body {
67 my $c = shift;
68 print $c->response->output;
69}
70
23f9d934 71=item $c->finalize_headers
fc7ec1d9 72
73=cut
74
75sub finalize_headers {
76 my $c = shift;
6dc87a0f 77
e7c0c583 78 $c->response->header( Status => $c->response->status );
6dc87a0f 79
e7c0c583 80 print $c->response->headers->as_string("\015\012");
81 print "\015\012";
fc7ec1d9 82}
83
06e1b616 84=item $c->prepare_body
fc7ec1d9 85
86=cut
87
06e1b616 88sub prepare_body {
fc7ec1d9 89 my $c = shift;
06e1b616 90
91 # XXX this is undocumented in CGI.pm. If Content-Type is not
92 # application/x-www-form-urlencoded or multipart/form-data
93 # CGI.pm will read STDIN into a param, POSTDATA.
94
e060fe05 95 $c->request->body( $c->cgi->param('POSTDATA') );
fc7ec1d9 96}
97
0556eb49 98=item $c->prepare_connection
99
100=cut
101
102sub prepare_connection {
103 my $c = shift;
e7c0c583 104 $c->req->hostname( $ENV{REMOTE_HOST} );
105 $c->req->address( $ENV{REMOTE_ADDR} );
0556eb49 106}
107
23f9d934 108=item $c->prepare_headers
fc7ec1d9 109
110=cut
111
112sub prepare_headers {
113 my $c = shift;
e7c0c583 114
115 while ( my ( $header, $value ) = each %ENV ) {
116
117 next unless $header =~ /^(HTTP|CONTENT)/i;
118
fc7ec1d9 119 ( my $field = $header ) =~ s/^HTTPS?_//;
e7c0c583 120
121 $c->req->headers->header( $field => $value );
fc7ec1d9 122 }
e7c0c583 123
124 $c->req->method( $ENV{REQUEST_METHOD} || 'GET' );
fc7ec1d9 125}
126
23f9d934 127=item $c->prepare_parameters
fc7ec1d9 128
129=cut
130
131sub prepare_parameters {
e7c0c583 132 my $c = shift;
5b387dfc 133
134 my ( @params );
b9e9fff6 135
136
137 if ( $c->request->method eq 'POST' ) {
e7c0c583 138
b9e9fff6 139 for my $param ( $c->cgi->url_param ) {
140 for my $value ( $c->cgi->url_param($param) ) {
141 push ( @params, $param, $value );
142 }
5b387dfc 143 }
fc7ec1d9 144 }
08cf3dd6 145
146 for my $param ( $c->cgi->param ) {
147 for my $value ( $c->cgi->param($param) ) {
5b387dfc 148 push ( @params, $param, $value );
149 }
150 }
08cf3dd6 151
5b387dfc 152 $c->req->_assign_values( $c->req->parameters, \@params );
fc7ec1d9 153}
154
23f9d934 155=item $c->prepare_path
fc7ec1d9 156
157=cut
158
159sub prepare_path {
160 my $c = shift;
8b4483b3 161
162 my $base;
163 {
164 my $scheme = $ENV{HTTPS} ? 'https' : 'http';
e7c0c583 165 my $host = $ENV{HTTP_HOST} || $ENV{SERVER_NAME};
8b4483b3 166 my $port = $ENV{SERVER_PORT} || 80;
167 my $path = $ENV{SCRIPT_NAME} || '/';
168
169 $base = URI->new;
170 $base->scheme($scheme);
171 $base->host($host);
172 $base->port($port);
173 $base->path($path);
174
175 $base = $base->canonical->as_string;
7833fdfc 176 }
8b4483b3 177
178 my $path = $ENV{PATH_INFO} || '/';
6dc87a0f 179 $path =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
e7c0c583 180 $path =~ s/^\///;
8b4483b3 181
182 $c->req->base($base);
183 $c->req->path($path);
fc7ec1d9 184}
185
23f9d934 186=item $c->prepare_request
fc7ec1d9 187
188=cut
189
e7c0c583 190sub prepare_request {
3f822a28 191 my ( $c, $cgi ) = @_;
192 $c->cgi( $cgi || CGI->new );
e7c0c583 193 $c->cgi->_reset_globals;
194}
fc7ec1d9 195
23f9d934 196=item $c->prepare_uploads
fc7ec1d9 197
198=cut
199
200sub prepare_uploads {
201 my $c = shift;
e7c0c583 202
203 my @uploads;
204
205 for my $param ( $c->cgi->param ) {
206
207 my @values = $c->cgi->param($param);
208
209 next unless ref( $values[0] );
210
211 for my $fh (@values) {
212
213 next unless my $size = ( stat $fh )[7];
214
215 my $info = $c->cgi->uploadInfo($fh);
216 my $tempname = $c->cgi->tmpFileName($fh);
217 my $type = $info->{'Content-Type'};
218 my $disposition = $info->{'Content-Disposition'};
219 my $filename = ( $disposition =~ / filename="([^;]*)"/ )[0];
220
146554c5 221 my $upload = Catalyst::Request::Upload->new(
e7c0c583 222 filename => $filename,
223 size => $size,
224 tempname => $tempname,
225 type => $type
146554c5 226 );
e7c0c583 227
228 push( @uploads, $param, $upload );
229 }
fc7ec1d9 230 }
e7c0c583 231
232 $c->req->_assign_values( $c->req->uploads, \@uploads );
fc7ec1d9 233}
234
c9afa5fc 235=item $c->run
236
237=cut
238
fc7ec1d9 239sub run { shift->handler }
240
23f9d934 241=back
242
fc7ec1d9 243=head1 SEE ALSO
244
245L<Catalyst>.
246
247=head1 AUTHOR
248
249Sebastian Riedel, C<sri@cpan.org>
250
251=head1 COPYRIGHT
252
253This program is free software, you can redistribute it and/or modify it under
254the same terms as Perl itself.
255
256=cut
257
2581;