doc patch from Andrew Ford
[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_cookies
110
111 Sets up cookies.
112
113 =cut
114
115 sub prepare_cookies { shift->req->cookies( { CGI::Cookie->fetch } ) }
116
117 =item $c->prepare_headers
118
119 =cut
120
121 sub prepare_headers {
122     my $c = shift;
123     $c->req->method( $c->cgi->request_method );
124     for my $header ( $c->cgi->http ) {
125         ( my $field = $header ) =~ s/^HTTPS?_//;
126         $c->req->headers->header( $field => $c->cgi->http($header) );
127     }
128 }
129
130 =item $c->prepare_parameters
131
132 =cut
133
134 sub prepare_parameters {
135     my $c    = shift;
136     my %vars = $c->cgi->Vars;
137     while ( my ( $key, $value ) = each %vars ) {
138         my @values = split "\0", $value;
139         $vars{$key} = @values <= 1 ? $values[0] : \@values;
140     }
141     $c->req->parameters( {%vars} );
142 }
143
144 =item $c->prepare_path
145
146 =cut
147
148 sub prepare_path {
149     my $c = shift;
150     $c->req->path( $c->cgi->url( -absolute => 1, -path_info => 1 ) );
151     my $loc = $c->cgi->url( -absolute => 1 );
152     no warnings 'uninitialized';
153     $c->req->{path} =~ s/^($loc)?\///;
154     $c->req->{path} .= '/' if $c->req->path eq $loc;
155     my $base = $c->cgi->url;
156     if ( $ENV{CATALYST_TEST} ) {
157         my $script = $c->cgi->script_name;
158         $base =~ s/$script$//i;
159     }
160     $base = URI->new($base);
161     $base->path('/') if ( $ENV{CATALYST_TEST} || !$base->path );
162     $c->req->base( $base->as_string );
163 }
164
165 =item $c->prepare_request
166
167 =cut
168
169 sub prepare_request { shift->cgi( CGI::Simple->new ) }
170
171 =item $c->prepare_uploads
172
173 =cut
174
175 sub prepare_uploads {
176     my $c = shift;
177     for my $name ( $c->cgi->upload ) {
178         $c->req->uploads->{$name} = {
179             fh   => $c->cgi->upload($name),
180             size => $c->cgi->upload_info( $name, 'size' ),
181             type => $c->cgi->upload_info( $name, 'mime' )
182         };
183     }
184 }
185
186 sub run { shift->handler }
187
188 =back
189
190 =head1 SEE ALSO
191
192 L<Catalyst>.
193
194 =head1 AUTHOR
195
196 Sebastian Riedel, C<sri@cpan.org>
197
198 =head1 COPYRIGHT
199
200 This program is free software, you can redistribute it and/or modify it under
201 the same terms as Perl itself.
202
203 =cut
204
205 1;