line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
|
2
|
|
|
|
|
|
|
use Moose; |
3
|
164
|
|
|
167
|
|
5336725
|
use Moose::Meta::Class (); |
|
164
|
|
|
|
|
15339919
|
|
|
164
|
|
|
|
|
1827
|
|
4
|
164
|
|
|
164
|
|
1138583
|
extends 'Catalyst::Component'; |
|
164
|
|
|
|
|
402
|
|
|
164
|
|
|
|
|
6069
|
|
5
|
|
|
|
|
|
|
use Moose::Util qw/find_meta/; |
6
|
164
|
|
|
164
|
|
994
|
use namespace::clean -except => 'meta'; |
|
164
|
|
|
|
|
369
|
|
|
164
|
|
|
|
|
1293
|
|
7
|
164
|
|
|
164
|
|
60602
|
use Catalyst::Exception; |
|
164
|
|
|
|
|
213505
|
|
|
164
|
|
|
|
|
1404
|
|
8
|
164
|
|
|
164
|
|
77313
|
use Catalyst::Exception::Detach; |
|
164
|
|
|
|
|
495
|
|
|
164
|
|
|
|
|
5227
|
|
9
|
164
|
|
|
164
|
|
76132
|
use Catalyst::Exception::Go; |
|
164
|
|
|
|
|
618
|
|
|
164
|
|
|
|
|
6338
|
|
10
|
164
|
|
|
164
|
|
85306
|
use Catalyst::Log; |
|
164
|
|
|
|
|
594
|
|
|
164
|
|
|
|
|
6042
|
|
11
|
164
|
|
|
164
|
|
84404
|
use Catalyst::Request; |
|
164
|
|
|
|
|
723
|
|
|
164
|
|
|
|
|
6859
|
|
12
|
164
|
|
|
164
|
|
104808
|
use Catalyst::Request::Upload; |
|
164
|
|
|
|
|
790
|
|
|
164
|
|
|
|
|
7532
|
|
13
|
164
|
|
|
164
|
|
92586
|
use Catalyst::Response; |
|
164
|
|
|
|
|
2218
|
|
|
164
|
|
|
|
|
7220
|
|
14
|
164
|
|
|
164
|
|
99663
|
use Catalyst::Utils; |
|
164
|
|
|
|
|
736
|
|
|
164
|
|
|
|
|
7385
|
|
15
|
164
|
|
|
164
|
|
1473
|
use Catalyst::Controller; |
|
164
|
|
|
|
|
397
|
|
|
164
|
|
|
|
|
4103
|
|
16
|
164
|
|
|
164
|
|
81436
|
use Data::OptList; |
|
164
|
|
|
|
|
730
|
|
|
164
|
|
|
|
|
8438
|
|
17
|
164
|
|
|
164
|
|
1468
|
use Devel::InnerPackage (); |
|
164
|
|
|
|
|
406
|
|
|
164
|
|
|
|
|
1754
|
|
18
|
164
|
|
|
164
|
|
4912
|
use Module::Pluggable::Object (); |
|
164
|
|
|
|
|
422
|
|
|
164
|
|
|
|
|
2495
|
|
19
|
164
|
|
|
164
|
|
99174
|
use Text::SimpleTable (); |
|
164
|
|
|
|
|
759169
|
|
|
164
|
|
|
|
|
4009
|
|
20
|
164
|
|
|
164
|
|
74180
|
use Path::Class::Dir (); |
|
164
|
|
|
|
|
405749
|
|
|
164
|
|
|
|
|
4064
|
|
21
|
164
|
|
|
164
|
|
1410
|
use Path::Class::File (); |
|
164
|
|
|
|
|
517
|
|
|
164
|
|
|
|
|
3183
|
|
22
|
164
|
|
|
164
|
|
1019
|
use URI (); |
|
164
|
|
|
|
|
451
|
|
|
164
|
|
|
|
|
2839
|
|
23
|
164
|
|
|
164
|
|
943
|
use URI::http; |
|
164
|
|
|
|
|
408
|
|
|
164
|
|
|
|
|
2641
|
|
24
|
164
|
|
|
164
|
|
905
|
use URI::https; |
|
164
|
|
|
|
|
388
|
|
|
164
|
|
|
|
|
5836
|
|
25
|
164
|
|
|
164
|
|
935
|
use HTML::Entities; |
|
164
|
|
|
|
|
433
|
|
|
164
|
|
|
|
|
3820
|
|
26
|
164
|
|
|
164
|
|
82085
|
use Tree::Simple qw/use_weak_refs/; |
|
164
|
|
|
|
|
946757
|
|
|
164
|
|
|
|
|
12782
|
|
27
|
164
|
|
|
164
|
|
93253
|
use Tree::Simple::Visitor::FindByUID; |
|
164
|
|
|
|
|
548878
|
|
|
164
|
|
|
|
|
918
|
|
28
|
164
|
|
|
164
|
|
79430
|
use Class::C3::Adopt::NEXT; |
|
164
|
|
|
|
|
351624
|
|
|
164
|
|
|
|
|
6563
|
|
29
|
164
|
|
|
164
|
|
1312
|
use List::Util qw/uniq/; |
|
164
|
|
|
|
|
420
|
|
|
164
|
|
|
|
|
2075
|
|
30
|
164
|
|
|
164
|
|
6035
|
use attributes; |
|
164
|
|
|
|
|
444
|
|
|
164
|
|
|
|
|
10979
|
|
31
|
164
|
|
|
164
|
|
1169
|
use String::RewritePrefix; |
|
164
|
|
|
|
|
427
|
|
|
164
|
|
|
|
|
1447
|
|
32
|
164
|
|
|
164
|
|
7317
|
use Catalyst::EngineLoader; |
|
164
|
|
|
|
|
511
|
|
|
164
|
|
|
|
|
1694
|
|
33
|
164
|
|
|
164
|
|
117649
|
use utf8; |
|
164
|
|
|
|
|
613
|
|
|
164
|
|
|
|
|
6927
|
|
34
|
164
|
|
|
164
|
|
1409
|
use Carp qw/croak carp shortmess/; |
|
164
|
|
|
|
|
419
|
|
|
164
|
|
|
|
|
1435
|
|
35
|
164
|
|
|
164
|
|
5083
|
use Try::Tiny; |
|
164
|
|
|
|
|
422
|
|
|
164
|
|
|
|
|
11479
|
|
36
|
164
|
|
|
164
|
|
1106
|
use Safe::Isa; |
|
164
|
|
|
|
|
396
|
|
|
164
|
|
|
|
|
7328
|
|
37
|
164
|
|
|
164
|
|
83627
|
use Moose::Util 'find_meta'; |
|
164
|
|
|
|
|
82707
|
|
|
164
|
|
|
|
|
21504
|
|
38
|
164
|
|
|
164
|
|
1311
|
use Plack::Middleware::Conditional; |
|
164
|
|
|
|
|
416
|
|
|
164
|
|
|
|
|
1722
|
|
39
|
164
|
|
|
164
|
|
118274
|
use Plack::Middleware::ReverseProxy; |
|
164
|
|
|
|
|
407680
|
|
|
164
|
|
|
|
|
5502
|
|
40
|
164
|
|
|
164
|
|
63820
|
use Plack::Middleware::IIS6ScriptNameFix; |
|
164
|
|
|
|
|
113512
|
|
|
164
|
|
|
|
|
5655
|
|
41
|
164
|
|
|
164
|
|
63869
|
use Plack::Middleware::IIS7KeepAliveFix; |
|
164
|
|
|
|
|
63340
|
|
|
164
|
|
|
|
|
5417
|
|
42
|
164
|
|
|
164
|
|
65660
|
use Plack::Middleware::LighttpdScriptNameFix; |
|
164
|
|
|
|
|
47278
|
|
|
164
|
|
|
|
|
5278
|
|
43
|
164
|
|
|
164
|
|
65283
|
use Plack::Middleware::ContentLength; |
|
164
|
|
|
|
|
56462
|
|
|
164
|
|
|
|
|
5387
|
|
44
|
164
|
|
|
164
|
|
64460
|
use Plack::Middleware::Head; |
|
164
|
|
|
|
|
50665
|
|
|
164
|
|
|
|
|
5178
|
|
45
|
164
|
|
|
164
|
|
63354
|
use Plack::Middleware::HTTPExceptions; |
|
164
|
|
|
|
|
42962
|
|
|
164
|
|
|
|
|
5080
|
|
46
|
164
|
|
|
164
|
|
66761
|
use Plack::Middleware::FixMissingBodyInRedirect; |
|
164
|
|
|
|
|
968485
|
|
|
164
|
|
|
|
|
6211
|
|
47
|
164
|
|
|
164
|
|
65873
|
use Plack::Middleware::MethodOverride; |
|
164
|
|
|
|
|
101528
|
|
|
164
|
|
|
|
|
5798
|
|
48
|
164
|
|
|
164
|
|
61966
|
use Plack::Middleware::RemoveRedundantBody; |
|
164
|
|
|
|
|
4994319
|
|
|
164
|
|
|
|
|
6530
|
|
49
|
164
|
|
|
164
|
|
69290
|
use Catalyst::Middleware::Stash; |
|
164
|
|
|
|
|
50119
|
|
|
164
|
|
|
|
|
5403
|
|
50
|
164
|
|
|
164
|
|
71754
|
use Plack::Util; |
|
164
|
|
|
|
|
515
|
|
|
164
|
|
|
|
|
6901
|
|
51
|
164
|
|
|
164
|
|
1101
|
use Class::Load 'load_class'; |
|
164
|
|
|
|
|
385
|
|
|
164
|
|
|
|
|
3561
|
|
52
|
164
|
|
|
164
|
|
844
|
use Encode 2.21 'decode_utf8', 'encode_utf8'; |
|
164
|
|
|
|
|
341
|
|
|
164
|
|
|
|
|
8468
|
|
53
|
164
|
|
|
164
|
|
975
|
use Scalar::Util; |
|
164
|
|
|
|
|
3861
|
|
|
164
|
|
|
|
|
6860
|
|
54
|
164
|
|
|
164
|
|
1688
|
|
|
164
|
|
|
|
|
398
|
|
|
164
|
|
|
|
|
10113
|
|
55
|
|
|
|
|
|
|
our $VERSION = '5.90130'; |
56
|
|
|
|
|
|
|
$VERSION =~ tr/_//d; |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
BEGIN { require 5.008003; } |
59
|
164
|
|
|
164
|
|
288741
|
|
60
|
|
|
|
|
|
|
has stack => (is => 'ro', default => sub { [] }); |
61
|
|
|
|
|
|
|
has state => (is => 'rw', default => 0); |
62
|
|
|
|
|
|
|
has stats => (is => 'rw'); |
63
|
|
|
|
|
|
|
has action => (is => 'rw'); |
64
|
|
|
|
|
|
|
has counter => (is => 'rw', default => sub { {} }); |
65
|
|
|
|
|
|
|
has request => ( |
66
|
|
|
|
|
|
|
is => 'rw', |
67
|
|
|
|
|
|
|
default => sub { |
68
|
|
|
|
|
|
|
my $self = shift; |
69
|
|
|
|
|
|
|
my $class = ref $self; |
70
|
|
|
|
|
|
|
my $composed_request_class = $class->composed_request_class; |
71
|
|
|
|
|
|
|
return $composed_request_class->new( $self->_build_request_constructor_args); |
72
|
|
|
|
|
|
|
}, |
73
|
|
|
|
|
|
|
predicate => 'has_request', |
74
|
|
|
|
|
|
|
lazy => 1, |
75
|
|
|
|
|
|
|
); |
76
|
|
|
|
|
|
|
my $self = shift; |
77
|
|
|
|
|
|
|
my %p = ( _log => $self->log ); |
78
|
934
|
|
|
934
|
|
1977
|
$p{_uploadtmp} = $self->_uploadtmp if $self->_has_uploadtmp; |
79
|
934
|
|
|
|
|
3121
|
$p{data_handlers} = {$self->registered_data_handlers}; |
80
|
934
|
100
|
|
|
|
33935
|
$p{_use_hash_multivalue} = $self->config->{use_hash_multivalue_in_request} |
81
|
934
|
|
|
|
|
4868
|
if $self->config->{use_hash_multivalue_in_request}; |
82
|
|
|
|
|
|
|
\%p; |
83
|
934
|
100
|
|
|
|
4012
|
} |
84
|
934
|
|
|
|
|
35355
|
|
85
|
|
|
|
|
|
|
my $class = shift; |
86
|
|
|
|
|
|
|
return $class->_composed_request_class if $class->_composed_request_class; |
87
|
|
|
|
|
|
|
|
88
|
1098
|
|
|
1098
|
1
|
2713
|
my @traits = (@{$class->request_class_traits||[]}, @{$class->config->{request_class_traits}||[]}); |
89
|
1098
|
100
|
|
|
|
5072
|
|
90
|
|
|
|
|
|
|
# For each trait listed, figure out what the namespace is. First we try the $trait |
91
|
162
|
100
|
|
|
|
479
|
# as it is in the config. Then try $MyApp::TraitFor::Request:$trait. Last we try |
|
162
|
50
|
|
|
|
1744
|
|
|
162
|
|
|
|
|
815
|
|
92
|
|
|
|
|
|
|
# Catalyst::TraitFor::Request::$trait. If none load, throw error. |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
my $trait_ns = 'TraitFor::Request'; |
95
|
|
|
|
|
|
|
my @normalized_traits = map { |
96
|
|
|
|
|
|
|
Class::Load::load_first_existing_class($_, $class.'::'.$trait_ns.'::'. $_, 'Catalyst::'.$trait_ns.'::'.$_) |
97
|
162
|
|
|
|
|
603
|
} @traits; |
98
|
|
|
|
|
|
|
|
99
|
162
|
|
|
|
|
595
|
if ($class->debug && scalar(@normalized_traits)) { |
|
6
|
|
|
|
|
1716
|
|
100
|
|
|
|
|
|
|
my $column_width = Catalyst::Utils::term_width() - 6; |
101
|
|
|
|
|
|
|
my $t = Text::SimpleTable->new($column_width); |
102
|
162
|
50
|
100
|
|
|
1283
|
$t->row($_) for @normalized_traits; |
103
|
0
|
|
|
|
|
0
|
$class->log->debug( "Composed Request Class Traits:\n" . $t->draw . "\n" ); |
104
|
0
|
|
|
|
|
0
|
} |
105
|
0
|
|
|
|
|
0
|
|
106
|
0
|
|
|
|
|
0
|
return $class->_composed_request_class(Moose::Util::with_traits($class->request_class, @normalized_traits)); |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
162
|
|
|
|
|
1963
|
has response => ( |
110
|
|
|
|
|
|
|
is => 'rw', |
111
|
|
|
|
|
|
|
default => sub { |
112
|
|
|
|
|
|
|
my $self = shift; |
113
|
|
|
|
|
|
|
my $class = ref $self; |
114
|
|
|
|
|
|
|
my $composed_response_class = $class->composed_response_class; |
115
|
|
|
|
|
|
|
return $composed_response_class->new( $self->_build_response_constructor_args); |
116
|
|
|
|
|
|
|
}, |
117
|
|
|
|
|
|
|
predicate=>'has_response', |
118
|
|
|
|
|
|
|
lazy => 1, |
119
|
|
|
|
|
|
|
); |
120
|
|
|
|
|
|
|
return +{ |
121
|
|
|
|
|
|
|
_log => $_[0]->log, |
122
|
|
|
|
|
|
|
encoding => $_[0]->encoding, |
123
|
|
|
|
|
|
|
}; |
124
|
|
|
|
|
|
|
} |
125
|
934
|
|
|
934
|
|
3965
|
|
126
|
|
|
|
|
|
|
my $class = shift; |
127
|
|
|
|
|
|
|
return $class->_composed_response_class if $class->_composed_response_class; |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
my @traits = (@{$class->response_class_traits||[]}, @{$class->config->{response_class_traits}||[]}); |
130
|
|
|
|
|
|
|
|
131
|
1097
|
|
|
1097
|
1
|
3968
|
my $trait_ns = 'TraitFor::Response'; |
132
|
1097
|
100
|
|
|
|
5555
|
my @normalized_traits = map { |
133
|
|
|
|
|
|
|
Class::Load::load_first_existing_class($_, $class.'::'.$trait_ns.'::'. $_, 'Catalyst::'.$trait_ns.'::'.$_) |
134
|
162
|
100
|
|
|
|
456
|
} @traits; |
|
162
|
50
|
|
|
|
1379
|
|
|
162
|
|
|
|
|
846
|
|
135
|
|
|
|
|
|
|
|
136
|
162
|
|
|
|
|
599
|
if ($class->debug && scalar(@normalized_traits)) { |
137
|
|
|
|
|
|
|
my $column_width = Catalyst::Utils::term_width() - 6; |
138
|
162
|
|
|
|
|
599
|
my $t = Text::SimpleTable->new($column_width); |
|
3
|
|
|
|
|
877
|
|
139
|
|
|
|
|
|
|
$t->row($_) for @normalized_traits; |
140
|
|
|
|
|
|
|
$class->log->debug( "Composed Response Class Traits:\n" . $t->draw . "\n" ); |
141
|
162
|
50
|
100
|
|
|
1039
|
} |
142
|
0
|
|
|
|
|
0
|
|
143
|
0
|
|
|
|
|
0
|
return $class->_composed_response_class(Moose::Util::with_traits($class->response_class, @normalized_traits)); |
144
|
0
|
|
|
|
|
0
|
} |
145
|
0
|
|
|
|
|
0
|
|
146
|
|
|
|
|
|
|
has namespace => (is => 'rw'); |
147
|
|
|
|
|
|
|
|
148
|
162
|
|
|
|
|
1705
|
|
149
|
|
|
|
|
|
|
my $self = shift; return $self->request(@_); |
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
my $self = shift; return $self->response(@_); |
152
|
|
|
|
|
|
|
} |
153
|
9219
|
50
|
|
9219
|
1
|
12584
|
|
|
9219
|
|
|
|
|
248021
|
|
154
|
15
|
|
|
15
|
1
|
1180
|
# For backwards compatibility |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
# For statistics |
157
|
23886
|
|
|
23886
|
1
|
84932
|
our $COUNT = 1; |
|
23886
|
|
|
|
|
561024
|
|
158
|
|
|
|
|
|
|
our $START = time; |
159
|
|
|
|
|
|
|
our $RECURSION = 1000; |
160
|
5494
|
|
|
5494
|
1
|
81185
|
our $DETACH = Catalyst::Exception::Detach->new; |
|
5494
|
|
|
|
|
138343
|
|
161
|
|
|
|
|
|
|
our $GO = Catalyst::Exception::Go->new; |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
#I imagine that very few of these really |
164
|
0
|
|
|
0
|
1
|
0
|
#need to be class variables. if any. |
165
|
|
|
|
|
|
|
#maybe we should just make them attributes with a default? |
166
|
|
|
|
|
|
|
__PACKAGE__->mk_classdata($_) |
167
|
|
|
|
|
|
|
for qw/components arguments dispatcher engine log dispatcher_class |
168
|
|
|
|
|
|
|
engine_loader context_class request_class response_class stats_class |
169
|
|
|
|
|
|
|
setup_finished _psgi_app loading_psgi_file run_options _psgi_middleware |
170
|
|
|
|
|
|
|
_data_handlers _encoding _encode_check finalized_default_middleware |
171
|
|
|
|
|
|
|
request_class_traits response_class_traits stats_class_traits |
172
|
|
|
|
|
|
|
_composed_request_class _composed_response_class _composed_stats_class/; |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
__PACKAGE__->dispatcher_class('Catalyst::Dispatcher'); |
175
|
|
|
|
|
|
|
__PACKAGE__->request_class('Catalyst::Request'); |
176
|
|
|
|
|
|
|
__PACKAGE__->response_class('Catalyst::Response'); |
177
|
|
|
|
|
|
|
__PACKAGE__->stats_class('Catalyst::Stats'); |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
my $class = shift; |
180
|
|
|
|
|
|
|
return $class->_composed_stats_class if $class->_composed_stats_class; |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
my @traits = (@{$class->stats_class_traits||[]}, @{$class->config->{stats_class_traits}||[]}); |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
my $trait_ns = 'TraitFor::Stats'; |
185
|
|
|
|
|
|
|
my @normalized_traits = map { |
186
|
|
|
|
|
|
|
Class::Load::load_first_existing_class($_, $class.'::'.$trait_ns.'::'. $_, 'Catalyst::'.$trait_ns.'::'.$_) |
187
|
|
|
|
|
|
|
} @traits; |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
if ($class->debug && scalar(@normalized_traits)) { |
190
|
163
|
|
|
163
|
1
|
1152
|
my $column_width = Catalyst::Utils::term_width() - 6; |
191
|
163
|
100
|
|
|
|
1327
|
my $t = Text::SimpleTable->new($column_width); |
192
|
|
|
|
|
|
|
$t->row($_) for @normalized_traits; |
193
|
162
|
100
|
|
|
|
539
|
$class->log->debug( "Composed Stats Class Traits:\n" . $t->draw . "\n" ); |
|
162
|
50
|
|
|
|
1426
|
|
|
162
|
|
|
|
|
976
|
|
194
|
|
|
|
|
|
|
} |
195
|
162
|
|
|
|
|
648
|
|
196
|
|
|
|
|
|
|
return $class->_composed_stats_class(Moose::Util::with_traits($class->stats_class, @normalized_traits)); |
197
|
162
|
|
|
|
|
576
|
} |
|
1
|
|
|
|
|
8
|
|
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
__PACKAGE__->_encode_check(Encode::FB_CROAK | Encode::LEAVE_SRC); |
200
|
162
|
50
|
100
|
|
|
990
|
|
201
|
0
|
|
|
|
|
0
|
my ( $class, @arguments ) = @_; |
202
|
0
|
|
|
|
|
0
|
|
203
|
0
|
|
|
|
|
0
|
# We have to limit $class to Catalyst to avoid pushing Catalyst upon every |
204
|
0
|
|
|
|
|
0
|
# callers @ISA. |
205
|
|
|
|
|
|
|
return unless $class eq 'Catalyst'; |
206
|
|
|
|
|
|
|
|
207
|
162
|
|
|
|
|
1497
|
my $caller = caller(); |
208
|
|
|
|
|
|
|
return if $caller eq 'main'; |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
my $meta = Moose::Meta::Class->initialize($caller); |
211
|
|
|
|
|
|
|
unless ( $caller->isa('Catalyst') ) { |
212
|
|
|
|
|
|
|
my @superclasses = ($meta->superclasses, $class, 'Catalyst::Controller'); |
213
|
315
|
|
|
315
|
|
111500
|
$meta->superclasses(@superclasses); |
214
|
|
|
|
|
|
|
} |
215
|
|
|
|
|
|
|
# Avoid possible C3 issues if 'Moose::Object' is already on RHS of MyApp |
216
|
|
|
|
|
|
|
$meta->superclasses(grep { $_ ne 'Moose::Object' } $meta->superclasses); |
217
|
315
|
100
|
|
|
|
21024
|
|
218
|
|
|
|
|
|
|
unless( $meta->has_method('meta') ){ |
219
|
166
|
|
|
|
|
584
|
if ($Moose::VERSION >= 1.15) { |
220
|
166
|
100
|
|
|
|
4842
|
$meta->_add_meta_method('meta'); |
221
|
|
|
|
|
|
|
} |
222
|
158
|
|
|
|
|
941
|
else { |
223
|
158
|
100
|
|
|
|
125293
|
$meta->add_method(meta => sub { Moose::Meta::Class->initialize("${caller}") } ); |
224
|
149
|
|
|
|
|
682
|
} |
225
|
149
|
|
|
|
|
7077
|
} |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
$caller->arguments( [@arguments] ); |
228
|
158
|
|
|
|
|
1076851
|
$caller->setup_home; |
|
315
|
|
|
|
|
8113
|
|
229
|
|
|
|
|
|
|
} |
230
|
158
|
100
|
|
|
|
289562
|
|
231
|
150
|
50
|
|
|
|
6140
|
|
232
|
150
|
|
|
|
|
905
|
=encoding UTF-8 |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
=head1 NAME |
235
|
0
|
|
|
0
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
236
|
|
|
|
|
|
|
Catalyst - The Elegant MVC Web Application Framework |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
=head1 SYNOPSIS |
239
|
158
|
|
|
|
|
50691
|
|
240
|
158
|
|
|
|
|
1147
|
See the L<Catalyst::Manual> distribution for comprehensive |
241
|
|
|
|
|
|
|
documentation and tutorials. |
242
|
|
|
|
|
|
|
|
243
|
887
|
|
|
887
|
|
2563
|
# Install Catalyst::Devel for helpers and other development tools |
244
|
|
|
|
|
|
|
# use the helper to create a new application |
245
|
|
|
|
|
|
|
catalyst.pl MyApp |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
# add models, views, controllers |
248
|
|
|
|
|
|
|
script/myapp_create.pl model MyDatabase DBIC::Schema create=static dbi:SQLite:/path/to/db |
249
|
|
|
|
|
|
|
script/myapp_create.pl view MyTemplate TT |
250
|
|
|
|
|
|
|
script/myapp_create.pl controller Search |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
# built in testserver -- use -r to restart automatically on changes |
253
|
|
|
|
|
|
|
# --help to see all available options |
254
|
|
|
|
|
|
|
script/myapp_server.pl |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
# command line testing interface |
257
|
|
|
|
|
|
|
script/myapp_test.pl /yada |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
### in lib/MyApp.pm |
260
|
|
|
|
|
|
|
use Catalyst qw/-Debug/; # include plugins here as well |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
### In lib/MyApp/Controller/Root.pm (autocreated) |
263
|
|
|
|
|
|
|
sub foo : Chained('/') Args() { # called for /foo, /foo/1, /foo/1/2, etc. |
264
|
|
|
|
|
|
|
my ( $self, $c, @args ) = @_; # args are qw/1 2/ for /foo/1/2 |
265
|
|
|
|
|
|
|
$c->stash->{template} = 'foo.tt'; # set the template |
266
|
|
|
|
|
|
|
# lookup something from db -- stash vars are passed to TT |
267
|
|
|
|
|
|
|
$c->stash->{data} = |
268
|
|
|
|
|
|
|
$c->model('Database::Foo')->search( { country => $args[0] } ); |
269
|
|
|
|
|
|
|
if ( $c->req->params->{bar} ) { # access GET or POST parameters |
270
|
|
|
|
|
|
|
$c->forward( 'bar' ); # process another action |
271
|
|
|
|
|
|
|
# do something else after forward returns |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
} |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
# The foo.tt TT template can use the stash data from the database |
276
|
|
|
|
|
|
|
[% WHILE (item = data.next) %] |
277
|
|
|
|
|
|
|
[% item.foo %] |
278
|
|
|
|
|
|
|
[% END %] |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
# called for /bar/of/soap, /bar/of/soap/10, etc. |
281
|
|
|
|
|
|
|
sub bar : Chained('/') PathPart('/bar/of/soap') Args() { ... } |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
# called after all actions are finished |
284
|
|
|
|
|
|
|
sub end : Action { |
285
|
|
|
|
|
|
|
my ( $self, $c ) = @_; |
286
|
|
|
|
|
|
|
if ( scalar @{ $c->error } ) { ... } # handle errors |
287
|
|
|
|
|
|
|
return if $c->res->body; # already have a response |
288
|
|
|
|
|
|
|
$c->forward( 'MyApp::View::TT' ); # render template |
289
|
|
|
|
|
|
|
} |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
See L<Catalyst::Manual::Intro> for additional information. |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
=head1 DESCRIPTION |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
Catalyst is a modern framework for making web applications without the |
296
|
|
|
|
|
|
|
pain usually associated with this process. This document is a reference |
297
|
|
|
|
|
|
|
to the main Catalyst application. If you are a new user, we suggest you |
298
|
|
|
|
|
|
|
start with L<Catalyst::Manual::Tutorial> or L<Catalyst::Manual::Intro>. |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
See L<Catalyst::Manual> for more documentation. |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
Catalyst plugins can be loaded by naming them as arguments to the "use |
303
|
|
|
|
|
|
|
Catalyst" statement. Omit the C<Catalyst::Plugin::> prefix from the |
304
|
|
|
|
|
|
|
plugin name, i.e., C<Catalyst::Plugin::My::Module> becomes |
305
|
|
|
|
|
|
|
C<My::Module>. |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
use Catalyst qw/My::Module/; |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
If your plugin starts with a name other than C<Catalyst::Plugin::>, you can |
310
|
|
|
|
|
|
|
fully qualify the name by using a unary plus: |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
use Catalyst qw/ |
313
|
|
|
|
|
|
|
My::Module |
314
|
|
|
|
|
|
|
+Fully::Qualified::Plugin::Name |
315
|
|
|
|
|
|
|
/; |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
Special flags like C<-Debug> can also be specified as |
318
|
|
|
|
|
|
|
arguments when Catalyst is loaded: |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
use Catalyst qw/-Debug My::Module/; |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
The position of plugins and flags in the chain is important, because |
323
|
|
|
|
|
|
|
they are loaded in the order in which they appear. |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
The following flags are supported: |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
=head2 -Debug |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
Enables debug output. You can also force this setting from the system |
330
|
|
|
|
|
|
|
environment with CATALYST_DEBUG or <MYAPP>_DEBUG. The environment |
331
|
|
|
|
|
|
|
settings override the application, with <MYAPP>_DEBUG having the highest |
332
|
|
|
|
|
|
|
priority. |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
This sets the log level to 'debug' and enables full debug output on the |
335
|
|
|
|
|
|
|
error screen. If you only want the latter, see L<< $c->debug >>. |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
=head2 -Home |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
Forces Catalyst to use a specific home directory, e.g.: |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
use Catalyst qw[-Home=/usr/mst]; |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
This can also be done in the shell environment by setting either the |
344
|
|
|
|
|
|
|
C<CATALYST_HOME> environment variable or C<MYAPP_HOME>; where C<MYAPP> |
345
|
|
|
|
|
|
|
is replaced with the uppercased name of your application, any "::" in |
346
|
|
|
|
|
|
|
the name will be replaced with underscores, e.g. MyApp::Web should use |
347
|
|
|
|
|
|
|
MYAPP_WEB_HOME. If both variables are set, the MYAPP_HOME one will be used. |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
If none of these are set, Catalyst will attempt to automatically detect the |
350
|
|
|
|
|
|
|
home directory. If you are working in a development environment, Catalyst |
351
|
|
|
|
|
|
|
will try and find the directory containing either Makefile.PL, Build.PL, |
352
|
|
|
|
|
|
|
dist.ini, or cpanfile. If the application has been installed into the system |
353
|
|
|
|
|
|
|
(i.e. you have done C<make install>), then Catalyst will use the path to your |
354
|
|
|
|
|
|
|
application module, without the .pm extension (e.g., /foo/MyApp if your |
355
|
|
|
|
|
|
|
application was installed at /foo/MyApp.pm) |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
=head2 -Log |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
use Catalyst '-Log=warn,fatal,error'; |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
Specifies a comma-delimited list of log levels. |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
=head2 -Stats |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
Enables statistics collection and reporting. |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
use Catalyst qw/-Stats=1/; |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
You can also force this setting from the system environment with CATALYST_STATS |
370
|
|
|
|
|
|
|
or <MYAPP>_STATS. The environment settings override the application, with |
371
|
|
|
|
|
|
|
<MYAPP>_STATS having the highest priority. |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
Stats are also enabled if L<< debugging |/"-Debug" >> is enabled. |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
=head1 METHODS |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
=head2 INFORMATION ABOUT THE CURRENT REQUEST |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
=head2 $c->action |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
Returns a L<Catalyst::Action> object for the current action, which |
382
|
|
|
|
|
|
|
stringifies to the action name. See L<Catalyst::Action>. |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
=head2 $c->namespace |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
Returns the namespace of the current action, i.e., the URI prefix |
387
|
|
|
|
|
|
|
corresponding to the controller of the current action. For example: |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
# in Controller::Foo::Bar |
390
|
|
|
|
|
|
|
$c->namespace; # returns 'foo/bar'; |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
=head2 $c->request |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
=head2 $c->req |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
Returns the current L<Catalyst::Request> object, giving access to |
397
|
|
|
|
|
|
|
information about the current client request (including parameters, |
398
|
|
|
|
|
|
|
cookies, HTTP headers, etc.). See L<Catalyst::Request>. |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
There is a predicate method C<has_request> that returns true if the |
401
|
|
|
|
|
|
|
request object has been created. This is something you might need to |
402
|
|
|
|
|
|
|
check if you are writing plugins that run before a request is finalized. |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
=head2 REQUEST FLOW HANDLING |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
=head2 $c->forward( $action [, \@arguments ] ) |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
=head2 $c->forward( $class, $method, [, \@arguments ] ) |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
=head2 $c->forward( $component_instance, $method, [, \@arguments ] ) |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
This is one way of calling another action (method) in the same or |
414
|
|
|
|
|
|
|
a different controller. You can also use C<< $self->my_method($c, @args) >> |
415
|
|
|
|
|
|
|
in the same controller or C<< $c->controller('MyController')->my_method($c, @args) >> |
416
|
|
|
|
|
|
|
in a different controller. |
417
|
|
|
|
|
|
|
The main difference is that 'forward' uses some of the Catalyst request |
418
|
|
|
|
|
|
|
cycle overhead, including debugging, which may be useful to you. On the |
419
|
|
|
|
|
|
|
other hand, there are some complications to using 'forward', restrictions |
420
|
|
|
|
|
|
|
on values returned from 'forward', and it may not handle errors as you prefer. |
421
|
|
|
|
|
|
|
Whether you use 'forward' or not is up to you; it is not considered superior to |
422
|
|
|
|
|
|
|
the other ways to call a method. |
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
'forward' calls another action, by its private name. If you give a |
425
|
|
|
|
|
|
|
class name but no method, C<process()> is called. You may also optionally |
426
|
|
|
|
|
|
|
pass arguments in an arrayref. The action will receive the arguments in |
427
|
|
|
|
|
|
|
C<@_> and C<< $c->req->args >>. Upon returning from the function, |
428
|
|
|
|
|
|
|
C<< $c->req->args >> will be restored to the previous values. |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
Any data C<return>ed from the action forwarded to, will be returned by the |
431
|
|
|
|
|
|
|
call to forward. |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
my $foodata = $c->forward('/foo'); |
434
|
|
|
|
|
|
|
$c->forward('index'); |
435
|
|
|
|
|
|
|
$c->forward(qw/Model::DBIC::Foo do_stuff/); |
436
|
|
|
|
|
|
|
$c->forward('View::TT'); |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
Note that L<< forward|/"$c->forward( $action [, \@arguments ] )" >> implies |
439
|
|
|
|
|
|
|
an C<< eval { } >> around the call (actually |
440
|
|
|
|
|
|
|
L<< execute|/"$c->execute( $class, $coderef )" >> does), thus rendering all |
441
|
|
|
|
|
|
|
exceptions thrown by the called action non-fatal and pushing them onto |
442
|
|
|
|
|
|
|
$c->error instead. If you want C<die> to propagate you need to do something |
443
|
|
|
|
|
|
|
like: |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
$c->forward('foo'); |
446
|
|
|
|
|
|
|
die join "\n", @{ $c->error } if @{ $c->error }; |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
Or make sure to always return true values from your actions and write |
449
|
|
|
|
|
|
|
your code like this: |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
$c->forward('foo') || return; |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
Another note is that C<< $c->forward >> always returns a scalar because it |
454
|
|
|
|
|
|
|
actually returns $c->state which operates in a scalar context. |
455
|
|
|
|
|
|
|
Thus, something like: |
456
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
return @array; |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
in an action that is forwarded to is going to return a scalar, |
460
|
|
|
|
|
|
|
i.e. how many items are in that array, which is probably not what you want. |
461
|
|
|
|
|
|
|
If you need to return an array then return a reference to it, |
462
|
|
|
|
|
|
|
or stash it like so: |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
$c->stash->{array} = \@array; |
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
and access it from the stash. |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
Keep in mind that the C<end> method used is that of the caller action. So a C<< $c->detach >> inside a forwarded action would run the C<end> method from the original action requested. |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
If you call c<forward> with the name of a component class or instance, rather than an action name |
471
|
|
|
|
|
|
|
or instance, we invoke the C<process> action on that class or instance, or whatever action you |
472
|
|
|
|
|
|
|
specific via the second argument $method. |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
=cut |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
=head2 $c->detach( $action [, \@arguments ] ) |
478
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
=head2 $c->detach( $class, $method, [, \@arguments ] ) |
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
=head2 $c->detach() |
482
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
The same as L<< forward|/"$c->forward( $action [, \@arguments ] )" >>, but |
484
|
|
|
|
|
|
|
doesn't return to the previous action when processing is finished. |
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
When called with no arguments it escapes the processing chain entirely. |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
=cut |
489
|
164
|
|
|
164
|
1
|
1188
|
|
|
164
|
|
|
6894
|
|
577
|
|
|
164
|
|
|
|
|
661583
|
|
|
6894
|
|
|
|
|
22971
|
|
|
6894
|
|
|
|
|
19285
|
|
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
=head2 $c->visit( $action [, \@arguments ] ) |
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
=head2 $c->visit( $action [, \@captures, \@arguments ] ) |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
=head2 $c->visit( $class, $method, [, \@arguments ] ) |
496
|
|
|
|
|
|
|
|
497
|
|
|
|
|
|
|
=head2 $c->visit( $class, $method, [, \@captures, \@arguments ] ) |
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
Almost the same as L<< forward|/"$c->forward( $action [, \@arguments ] )" >>, |
500
|
|
|
|
|
|
|
but does a full dispatch, instead of just calling the new C<$action> / |
501
|
|
|
|
|
|
|
C<< $class->$method >>. This means that C<begin>, C<auto> and the method |
502
|
|
|
|
|
|
|
you go to are called, just like a new request. |
503
|
|
|
|
|
|
|
|
504
|
16
|
|
|
16
|
1
|
186
|
In addition both C<< $c->action >> and C<< $c->namespace >> are localized. |
|
16
|
|
|
|
|
85
|
|
505
|
|
|
|
|
|
|
This means, for example, that C<< $c->action >> methods such as |
506
|
|
|
|
|
|
|
L<name|Catalyst::Action/name>, L<class|Catalyst::Action/class> and |
507
|
|
|
|
|
|
|
L<reverse|Catalyst::Action/reverse> return information for the visited action |
508
|
|
|
|
|
|
|
when they are invoked within the visited action. This is different from the |
509
|
|
|
|
|
|
|
behavior of L<< forward|/"$c->forward( $action [, \@arguments ] )" >>, which |
510
|
|
|
|
|
|
|
continues to use the $c->action object from the caller action even when |
511
|
|
|
|
|
|
|
invoked from the called action. |
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
C<< $c->stash >> is kept unchanged. |
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
In effect, L<< visit|/"$c->visit( $action [, \@captures, \@arguments ] )" >> |
516
|
|
|
|
|
|
|
allows you to "wrap" another action, just as it would have been called by |
517
|
|
|
|
|
|
|
dispatching from a URL, while the analogous |
518
|
|
|
|
|
|
|
L<< go|/"$c->go( $action [, \@captures, \@arguments ] )" >> allows you to |
519
|
|
|
|
|
|
|
transfer control to another action as if it had been reached directly from a URL. |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
=cut |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
=head2 $c->go( $action [, \@arguments ] ) |
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
=head2 $c->go( $action [, \@captures, \@arguments ] ) |
527
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
=head2 $c->go( $class, $method, [, \@arguments ] ) |
529
|
|
|
|
|
|
|
|
530
|
|
|
|
|
|
|
=head2 $c->go( $class, $method, [, \@captures, \@arguments ] ) |
531
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
The relationship between C<go> and |
533
|
|
|
|
|
|
|
L<< visit|/"$c->visit( $action [, \@captures, \@arguments ] )" >> is the same as |
534
|
|
|
|
|
|
|
the relationship between |
535
|
|
|
|
|
|
|
L<< forward|/"$c->forward( $class, $method, [, \@arguments ] )" >> and |
536
|
|
|
|
|
|
|
L<< detach|/"$c->detach( $action [, \@arguments ] )" >>. Like C<< $c->visit >>, |
537
|
|
|
|
|
|
|
C<< $c->go >> will perform a full dispatch on the specified action or method, |
538
|
26
|
|
|
26
|
1
|
264
|
with localized C<< $c->action >> and C<< $c->namespace >>. Like C<detach>, |
|
26
|
|
|
|
|
83
|
|
539
|
|
|
|
|
|
|
C<go> escapes the processing of the current request chain on completion, and |
540
|
|
|
|
|
|
|
does not return to its caller. |
541
|
|
|
|
|
|
|
|
542
|
|
|
|
|
|
|
@arguments are arguments to the final destination of $action. @captures are |
543
|
|
|
|
|
|
|
arguments to the intermediate steps, if any, on the way to the final sub of |
544
|
|
|
|
|
|
|
$action. |
545
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
=cut |
547
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
=head2 $c->response |
550
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
=head2 $c->res |
552
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
Returns the current L<Catalyst::Response> object, see there for details. |
554
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
There is a predicate method C<has_response> that returns true if the |
556
|
|
|
|
|
|
|
request object has been created. This is something you might need to |
557
|
|
|
|
|
|
|
check if you are writing plugins that run before a request is finalized. |
558
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
=head2 $c->stash |
560
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
Returns a hashref to the stash, which may be used to store data and pass |
562
|
|
|
|
|
|
|
it between components during a request. You can also set hash keys by |
563
|
|
|
|
|
|
|
passing arguments. The stash is automatically sent to the view. The |
564
|
24
|
|
|
24
|
1
|
224
|
stash is cleared at the end of a request; it cannot be used for |
|
24
|
|
|
|
|
76
|
|
565
|
|
|
|
|
|
|
persistent storage (for this you must use a session; see |
566
|
|
|
|
|
|
|
L<Catalyst::Plugin::Session> for a complete system integrated with |
567
|
|
|
|
|
|
|
Catalyst). |
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
$c->stash->{foo} = $bar; |
570
|
|
|
|
|
|
|
$c->stash( { moose => 'majestic', qux => 0 } ); |
571
|
|
|
|
|
|
|
$c->stash( bar => 1, gorch => 2 ); # equivalent to passing a hashref |
572
|
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
# stash is automatically passed to the view for use in a template |
574
|
|
|
|
|
|
|
$c->forward( 'MyApp::View::TT' ); |
575
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
The stash hash is currently stored in the PSGI C<$env> and is managed by |
577
|
|
|
|
|
|
|
L<Catalyst::Middleware::Stash>. Since it's part of the C<$env> items in |
578
|
|
|
|
|
|
|
the stash can be accessed in sub applications mounted under your main |
579
|
|
|
|
|
|
|
L<Catalyst> application. For example if you delegate the response of an |
580
|
|
|
|
|
|
|
action to another L<Catalyst> application, that sub application will have |
581
|
|
|
|
|
|
|
access to all the stash keys of the main one, and if can of course add |
582
|
|
|
|
|
|
|
more keys of its own. However those new keys will not 'bubble' back up |
583
|
|
|
|
|
|
|
to the main application. |
584
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
For more information the best thing to do is to review the test case: |
586
|
|
|
|
|
|
|
t/middleware-stash.t in the distribution /t directory. |
587
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
=cut |
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
my $c = shift; |
591
|
|
|
|
|
|
|
$c->log->error("You are requesting the stash but you don't have a context") unless blessed $c; |
592
|
|
|
|
|
|
|
return Catalyst::Middleware::Stash::get_stash($c->req->env)->(@_); |
593
|
|
|
|
|
|
|
} |
594
|
|
|
|
|
|
|
|
595
|
|
|
|
|
|
|
=head2 $c->error |
596
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
=head2 $c->error($error, ...) |
598
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
=head2 $c->error($arrayref) |
600
|
|
|
|
|
|
|
|
601
|
|
|
|
|
|
|
Returns an arrayref containing error messages. If Catalyst encounters an |
602
|
|
|
|
|
|
|
error while processing a request, it stores the error in $c->error. This |
603
|
|
|
|
|
|
|
method should only be used to store fatal error messages. |
604
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
my @error = @{ $c->error }; |
606
|
|
|
|
|
|
|
|
607
|
|
|
|
|
|
|
Add a new error. |
608
|
2416
|
|
|
2416
|
1
|
8799
|
|
609
|
2416
|
50
|
|
|
|
9241
|
$c->error('Something bad happened'); |
610
|
2416
|
|
|
|
|
7359
|
|
611
|
|
|
|
|
|
|
Calling this will always return an arrayref (if there are no errors it |
612
|
|
|
|
|
|
|
will be an empty arrayref. |
613
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
=cut |
615
|
|
|
|
|
|
|
|
616
|
|
|
|
|
|
|
my $c = shift; |
617
|
|
|
|
|
|
|
if ( $_[0] ) { |
618
|
|
|
|
|
|
|
my $error = ref $_[0] eq 'ARRAY' ? $_[0] : [@_]; |
619
|
|
|
|
|
|
|
croak @$error unless ref $c; |
620
|
|
|
|
|
|
|
push @{ $c->{error} }, @$error; |
621
|
|
|
|
|
|
|
} |
622
|
|
|
|
|
|
|
elsif ( defined $_[0] ) { $c->{error} = undef } |
623
|
|
|
|
|
|
|
return $c->{error} || []; |
624
|
|
|
|
|
|
|
} |
625
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
=head2 $c->state |
627
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
Contains the return value of the last executed action. |
629
|
|
|
|
|
|
|
Note that << $c->state >> operates in a scalar context which means that all |
630
|
|
|
|
|
|
|
values it returns are scalar. |
631
|
|
|
|
|
|
|
|
632
|
|
|
|
|
|
|
Please note that if an action throws an exception, the value of state |
633
|
|
|
|
|
|
|
should no longer be considered the return if the last action. It is generally |
634
|
|
|
|
|
|
|
going to be 0, which indicates an error state. Examine $c->error for error |
635
|
11038
|
|
|
11038
|
1
|
127275
|
details. |
636
|
11038
|
100
|
|
|
|
28514
|
|
|
|
100
|
|
|
|
|
|
637
|
39
|
50
|
|
|
|
214
|
=head2 $c->clear_errors |
638
|
39
|
50
|
|
|
|
166
|
|
639
|
39
|
|
|
|
|
82
|
Clear errors. You probably don't want to clear the errors unless you are |
|
39
|
|
|
|
|
197
|
|
640
|
|
|
|
|
|
|
implementing a custom error screen. |
641
|
10
|
|
|
|
|
19
|
|
642
|
11038
|
|
100
|
|
|
59860
|
This is equivalent to running |
643
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
$c->error(0); |
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
=cut |
647
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
my $c = shift; |
649
|
|
|
|
|
|
|
$c->error(0); |
650
|
|
|
|
|
|
|
} |
651
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
=head2 $c->has_errors |
653
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
Returns true if you have errors |
655
|
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
=cut |
657
|
|
|
|
|
|
|
|
658
|
|
|
|
|
|
|
|
659
|
|
|
|
|
|
|
=head2 $c->last_error |
660
|
|
|
|
|
|
|
|
661
|
|
|
|
|
|
|
Returns the most recent error in the stack (the one most recently added...) |
662
|
|
|
|
|
|
|
or nothing if there are no errors. This does not modify the contents of the |
663
|
|
|
|
|
|
|
error stack. |
664
|
|
|
|
|
|
|
|
665
|
|
|
|
|
|
|
=cut |
666
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
my (@errs) = @{shift->error}; |
668
|
10
|
|
|
10
|
1
|
18
|
return scalar(@errs) ? $errs[-1]: undef; |
669
|
10
|
|
|
|
|
21
|
} |
670
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
=head2 shift_errors |
672
|
|
|
|
|
|
|
|
673
|
|
|
|
|
|
|
shifts the most recently added error off the error stack and returns it. Returns |
674
|
|
|
|
|
|
|
nothing if there are no more errors. |
675
|
|
|
|
|
|
|
|
676
|
|
|
|
|
|
|
=cut |
677
|
|
|
|
|
|
|
|
678
|
292
|
100
|
|
292
|
1
|
545
|
my ($self) = @_; |
|
292
|
|
|
|
|
980
|
|
679
|
|
|
|
|
|
|
my @errors = @{$self->error}; |
680
|
|
|
|
|
|
|
my $err = shift(@errors); |
681
|
|
|
|
|
|
|
$self->{error} = \@errors; |
682
|
|
|
|
|
|
|
return $err; |
683
|
|
|
|
|
|
|
} |
684
|
|
|
|
|
|
|
|
685
|
|
|
|
|
|
|
=head2 pop_errors |
686
|
|
|
|
|
|
|
|
687
|
|
|
|
|
|
|
pops the most recently added error off the error stack and returns it. Returns |
688
|
|
|
|
|
|
|
nothing if there are no more errors. |
689
|
0
|
|
|
0
|
1
|
0
|
|
|
0
|
|
|
|
|
0
|
|
690
|
0
|
0
|
|
|
|
0
|
=cut |
691
|
|
|
|
|
|
|
|
692
|
|
|
|
|
|
|
my ($self) = @_; |
693
|
|
|
|
|
|
|
my @errors = @{$self->error}; |
694
|
|
|
|
|
|
|
my $err = pop(@errors); |
695
|
|
|
|
|
|
|
$self->{error} = \@errors; |
696
|
|
|
|
|
|
|
return $err; |
697
|
|
|
|
|
|
|
} |
698
|
|
|
|
|
|
|
|
699
|
|
|
|
|
|
|
my $c = shift; |
700
|
|
|
|
|
|
|
return map $c->components->{ $_ }, $c->_comp_names_search_prefixes(@_); |
701
|
3
|
|
|
3
|
1
|
27
|
} |
702
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
7
|
|
703
|
3
|
|
|
|
|
8
|
# search components given a name and some prefixes |
704
|
3
|
|
|
|
|
9
|
my ( $c, $name, @prefixes ) = @_; |
705
|
3
|
|
|
|
|
8
|
my $appclass = ref $c || $c; |
706
|
|
|
|
|
|
|
my $filter = "^${appclass}::(" . join( '|', @prefixes ) . ')::'; |
707
|
|
|
|
|
|
|
$filter = qr/$filter/; # Compile regex now rather than once per loop |
708
|
|
|
|
|
|
|
|
709
|
|
|
|
|
|
|
# map the original component name to the sub part that we will search against |
710
|
|
|
|
|
|
|
my %eligible = map { my $n = $_; $n =~ s{^$appclass\::[^:]+::}{}; $_ => $n; } |
711
|
|
|
|
|
|
|
grep { /$filter/ } keys %{ $c->components }; |
712
|
|
|
|
|
|
|
|
713
|
|
|
|
|
|
|
# undef for a name will return all |
714
|
|
|
|
|
|
|
return keys %eligible if !defined $name; |
715
|
|
|
|
|
|
|
|
716
|
0
|
|
|
0
|
1
|
0
|
my $query = $name->$_isa('Regexp') ? $name : qr/^$name$/i; |
717
|
0
|
|
|
|
|
0
|
my @result = grep { $eligible{$_} =~ m{$query} } keys %eligible; |
|
0
|
|
|
|
|
0
|
|
718
|
0
|
|
|
|
|
0
|
|
719
|
0
|
|
|
|
|
0
|
return @result if @result; |
720
|
0
|
|
|
|
|
0
|
|
721
|
|
|
|
|
|
|
# if we were given a regexp to search against, we're done. |
722
|
|
|
|
|
|
|
return if $name->$_isa('Regexp'); |
723
|
|
|
|
|
|
|
|
724
|
64
|
|
|
64
|
|
130
|
# skip regexp fallback if configured |
725
|
64
|
|
|
|
|
215
|
return |
726
|
|
|
|
|
|
|
if $appclass->config->{disable_component_resolution_regex_fallback}; |
727
|
|
|
|
|
|
|
|
728
|
|
|
|
|
|
|
# regexp fallback |
729
|
|
|
|
|
|
|
$query = qr/$name/i; |
730
|
67
|
|
|
67
|
|
208
|
@result = grep { $eligible{ $_ } =~ m{$query} } keys %eligible; |
731
|
67
|
|
66
|
|
|
221
|
|
732
|
67
|
|
|
|
|
267
|
# no results? try against full names |
733
|
67
|
|
|
|
|
1313
|
if( !@result ) { |
734
|
|
|
|
|
|
|
@result = grep { m{$query} } keys %eligible; |
735
|
|
|
|
|
|
|
} |
736
|
574
|
|
|
|
|
814
|
|
|
574
|
|
|
|
|
2165
|
|
|
574
|
|
|
|
|
1600
|
|
737
|
67
|
|
|
|
|
170
|
# don't warn if we didn't find any results, it just might not exist |
|
1139
|
|
|
|
|
3617
|
|
|
67
|
|
|
|
|
203
|
|
738
|
|
|
|
|
|
|
if( @result ) { |
739
|
|
|
|
|
|
|
# Disgusting hack to work out correct method name |
740
|
67
|
100
|
|
|
|
288
|
my $warn_for = lc $prefixes[0]; |
741
|
|
|
|
|
|
|
my $msg = "Used regexp fallback for \$c->${warn_for}('${name}'), which found '" . |
742
|
61
|
100
|
|
|
|
215
|
(join '", "', @result) . "'. Relying on regexp fallback behavior for " . |
743
|
61
|
|
|
|
|
1252
|
"component resolution is unreliable and unsafe."; |
|
558
|
|
|
|
|
1596
|
|
744
|
|
|
|
|
|
|
my $short = $result[0]; |
745
|
61
|
100
|
|
|
|
496
|
# remove the component namespace prefix |
746
|
|
|
|
|
|
|
$short =~ s/.*?(Model|Controller|View):://; |
747
|
|
|
|
|
|
|
my $shortmess = Carp::shortmess(''); |
748
|
20
|
100
|
|
|
|
59
|
if ($shortmess =~ m#Catalyst/Plugin#) { |
749
|
|
|
|
|
|
|
$msg .= " You probably need to set '$short' instead of '${name}' in this " . |
750
|
|
|
|
|
|
|
"plugin's config"; |
751
|
|
|
|
|
|
|
} elsif ($shortmess =~ m#Catalyst/lib/(View|Controller)#) { |
752
|
19
|
100
|
|
|
|
210
|
$msg .= " You probably need to set '$short' instead of '${name}' in this " . |
753
|
|
|
|
|
|
|
"component's config"; |
754
|
|
|
|
|
|
|
} else { |
755
|
18
|
|
|
|
|
177
|
$msg .= " You probably meant \$c->${warn_for}('$short') instead of \$c->${warn_for}('${name}'), " . |
756
|
18
|
|
|
|
|
76
|
"but if you really wanted to search, pass in a regexp as the argument " . |
|
139
|
|
|
|
|
362
|
|
757
|
|
|
|
|
|
|
"like so: \$c->${warn_for}(qr/${name}/)"; |
758
|
|
|
|
|
|
|
} |
759
|
18
|
100
|
|
|
|
60
|
$c->log->warn( "${msg}$shortmess" ); |
760
|
14
|
|
|
|
|
36
|
} |
|
125
|
|
|
|
|
344
|
|
761
|
|
|
|
|
|
|
|
762
|
|
|
|
|
|
|
return @result; |
763
|
|
|
|
|
|
|
} |
764
|
18
|
100
|
|
|
|
53
|
|
765
|
|
|
|
|
|
|
# Find possible names for a prefix |
766
|
14
|
|
|
|
|
33
|
my ( $c, @prefixes ) = @_; |
767
|
14
|
|
|
|
|
59
|
my $appclass = ref $c || $c; |
768
|
|
|
|
|
|
|
|
769
|
|
|
|
|
|
|
my $filter = "^${appclass}::(" . join( '|', @prefixes ) . ')::'; |
770
|
14
|
|
|
|
|
32
|
|
771
|
|
|
|
|
|
|
my @names = map { s{$filter}{}; $_; } |
772
|
14
|
|
|
|
|
112
|
$c->_comp_names_search_prefixes( undef, @prefixes ); |
773
|
14
|
|
|
|
|
1870
|
|
774
|
14
|
50
|
|
|
|
181
|
return @names; |
|
|
50
|
|
|
|
|
|
775
|
0
|
|
|
|
|
0
|
} |
776
|
|
|
|
|
|
|
|
777
|
|
|
|
|
|
|
# Filter a component before returning by calling ACCEPT_CONTEXT if available |
778
|
0
|
|
|
|
|
0
|
|
779
|
|
|
|
|
|
|
my ( $c, $comp, @args ) = @_; |
780
|
|
|
|
|
|
|
|
781
|
14
|
|
|
|
|
62
|
if(ref $comp eq 'CODE') { |
782
|
|
|
|
|
|
|
$comp = $comp->(); |
783
|
|
|
|
|
|
|
} |
784
|
|
|
|
|
|
|
|
785
|
14
|
|
|
|
|
62
|
if ( eval { $comp->can('ACCEPT_CONTEXT'); } ) { |
786
|
|
|
|
|
|
|
return $comp->ACCEPT_CONTEXT( $c, @args ); |
787
|
|
|
|
|
|
|
} |
788
|
18
|
|
|
|
|
143
|
|
789
|
|
|
|
|
|
|
$c->log->warn("You called component '${\$comp->catalyst_component_name}' with arguments [@args], but this component does not ACCEPT_CONTEXT, so args are ignored.") if scalar(@args) && $c->debug; |
790
|
|
|
|
|
|
|
|
791
|
|
|
|
|
|
|
return $comp; |
792
|
|
|
|
|
|
|
} |
793
|
3
|
|
|
3
|
|
11
|
|
794
|
3
|
|
33
|
|
|
14
|
=head2 COMPONENT ACCESSORS |
795
|
|
|
|
|
|
|
|
796
|
3
|
|
|
|
|
14
|
=head2 $c->controller($name) |
797
|
|
|
|
|
|
|
|
798
|
3
|
|
|
|
|
11
|
Gets a L<Catalyst::Controller> instance by name. |
|
9
|
|
|
|
|
86
|
|
|
9
|
|
|
|
|
24
|
|
799
|
|
|
|
|
|
|
|
800
|
|
|
|
|
|
|
$c->controller('Foo')->do_stuff; |
801
|
3
|
|
|
|
|
32
|
|
802
|
|
|
|
|
|
|
If the name is omitted, will return the controller for the dispatched |
803
|
|
|
|
|
|
|
action. |
804
|
|
|
|
|
|
|
|
805
|
|
|
|
|
|
|
If you want to search for controllers, pass in a regexp as the argument. |
806
|
|
|
|
|
|
|
|
807
|
16565
|
|
|
16565
|
|
31990
|
# find all controllers that start with Foo |
808
|
|
|
|
|
|
|
my @foo_controllers = $c->controller(qr{^Foo}); |
809
|
16565
|
100
|
|
|
|
40804
|
|
810
|
9
|
|
|
|
|
25
|
|
811
|
|
|
|
|
|
|
=cut |
812
|
|
|
|
|
|
|
|
813
|
16565
|
100
|
|
|
|
26318
|
my ( $c, $name, @args ) = @_; |
|
16565
|
|
|
|
|
63411
|
|
814
|
11
|
|
|
|
|
45
|
|
815
|
|
|
|
|
|
|
my $appclass = ref($c) || $c; |
816
|
|
|
|
|
|
|
if( $name ) { |
817
|
16554
|
50
|
33
|
|
|
40523
|
unless ( $name->$_isa('Regexp') ) { # Direct component hash lookup to avoid costly regexps |
|
0
|
|
|
|
|
0
|
|
818
|
|
|
|
|
|
|
my $comps = $c->components; |
819
|
16554
|
|
|
|
|
50122
|
my $check = $appclass."::Controller::".$name; |
820
|
|
|
|
|
|
|
return $c->_filter_component( $comps->{$check}, @args ) if exists $comps->{$check}; |
821
|
|
|
|
|
|
|
foreach my $path (@{$appclass->config->{ setup_components }->{ search_extra }}) { |
822
|
|
|
|
|
|
|
next unless $path =~ /.*::Controller/; |
823
|
|
|
|
|
|
|
$check = $path."::".$name; |
824
|
|
|
|
|
|
|
return $c->_filter_component( $comps->{$check}, @args ) if exists $comps->{$check}; |
825
|
|
|
|
|
|
|
} |
826
|
|
|
|
|
|
|
} |
827
|
|
|
|
|
|
|
my @result = $c->_comp_search_prefixes( $name, qw/Controller C/ ); |
828
|
|
|
|
|
|
|
return map { $c->_filter_component( $_, @args ) } @result if ref $name; |
829
|
|
|
|
|
|
|
return $c->_filter_component( $result[ 0 ], @args ); |
830
|
|
|
|
|
|
|
} |
831
|
|
|
|
|
|
|
|
832
|
|
|
|
|
|
|
return $c->component( $c->action->class ); |
833
|
|
|
|
|
|
|
} |
834
|
|
|
|
|
|
|
|
835
|
|
|
|
|
|
|
=head2 $c->model($name) |
836
|
|
|
|
|
|
|
|
837
|
|
|
|
|
|
|
Gets a L<Catalyst::Model> instance by name. |
838
|
|
|
|
|
|
|
|
839
|
|
|
|
|
|
|
$c->model('Foo')->do_stuff; |
840
|
|
|
|
|
|
|
|
841
|
|
|
|
|
|
|
Any extra arguments are directly passed to ACCEPT_CONTEXT, if the model |
842
|
71
|
|
|
71
|
1
|
14656
|
defines ACCEPT_CONTEXT. If it does not, the args are discarded. |
843
|
|
|
|
|
|
|
|
844
|
71
|
|
66
|
|
|
300
|
If the name is omitted, it will look for |
845
|
71
|
100
|
|
|
|
198
|
- a model object in $c->stash->{current_model_instance}, then |
846
|
61
|
100
|
|
|
|
246
|
- a model name in $c->stash->{current_model}, then |
847
|
58
|
|
|
|
|
747
|
- a config setting 'default_model', or |
848
|
58
|
|
|
|
|
164
|
- check if there is only one model, and return it if that's the case. |
849
|
58
|
100
|
|
|
|
308
|
|
850
|
13
|
|
|
|
|
20
|
If you want to search for models, pass in a regexp as the argument. |
|
13
|
|
|
|
|
48
|
|
851
|
2
|
100
|
|
|
|
13
|
|
852
|
1
|
|
|
|
|
5
|
# find all models that start with Foo |
853
|
1
|
50
|
|
|
|
13
|
my @foo_models = $c->model(qr{^Foo}); |
854
|
|
|
|
|
|
|
|
855
|
|
|
|
|
|
|
=cut |
856
|
15
|
|
|
|
|
96
|
|
857
|
15
|
100
|
|
|
|
67
|
my ( $c, $name, @args ) = @_; |
|
3
|
|
|
|
|
9
|
|
858
|
12
|
|
|
|
|
37
|
my $appclass = ref($c) || $c; |
859
|
|
|
|
|
|
|
if( $name ) { |
860
|
|
|
|
|
|
|
unless ( $name->$_isa('Regexp') ) { # Direct component hash lookup to avoid costly regexps |
861
|
10
|
|
|
|
|
223
|
my $comps = $c->components; |
862
|
|
|
|
|
|
|
my $check = $appclass."::Model::".$name; |
863
|
|
|
|
|
|
|
return $c->_filter_component( $comps->{$check}, @args ) if exists $comps->{$check}; |
864
|
|
|
|
|
|
|
foreach my $path (@{$appclass->config->{ setup_components }->{ search_extra }}) { |
865
|
|
|
|
|
|
|
next unless $path =~ /.*::Model/; |
866
|
|
|
|
|
|
|
$check = $path."::".$name; |
867
|
|
|
|
|
|
|
return $c->_filter_component( $comps->{$check}, @args ) if exists $comps->{$check}; |
868
|
|
|
|
|
|
|
} |
869
|
|
|
|
|
|
|
} |
870
|
|
|
|
|
|
|
my @result = $c->_comp_search_prefixes( $name, qw/Model M/ ); |
871
|
|
|
|
|
|
|
return map { $c->_filter_component( $_, @args ) } @result if ref $name; |
872
|
|
|
|
|
|
|
return $c->_filter_component( $result[ 0 ], @args ); |
873
|
|
|
|
|
|
|
} |
874
|
|
|
|
|
|
|
|
875
|
|
|
|
|
|
|
if (ref $c) { |
876
|
|
|
|
|
|
|
return $c->stash->{current_model_instance} |
877
|
|
|
|
|
|
|
if $c->stash->{current_model_instance}; |
878
|
|
|
|
|
|
|
return $c->model( $c->stash->{current_model} ) |
879
|
|
|
|
|
|
|
if $c->stash->{current_model}; |
880
|
|
|
|
|
|
|
} |
881
|
|
|
|
|
|
|
return $c->model( $appclass->config->{default_model} ) |
882
|
|
|
|
|
|
|
if $appclass->config->{default_model}; |
883
|
|
|
|
|
|
|
|
884
|
|
|
|
|
|
|
my( $comp, $rest ) = $c->_comp_search_prefixes( undef, qw/Model M/); |
885
|
|
|
|
|
|
|
|
886
|
|
|
|
|
|
|
if( $rest ) { |
887
|
51
|
|
|
51
|
1
|
8304
|
$c->log->warn( Carp::shortmess('Calling $c->model() will return a random model unless you specify one of:') ); |
888
|
51
|
|
66
|
|
|
230
|
$c->log->warn( '* $c->config(default_model => "the name of the default model to use")' ); |
889
|
51
|
100
|
|
|
|
164
|
$c->log->warn( '* $c->stash->{current_model} # the name of the model to use for this request' ); |
890
|
49
|
100
|
|
|
|
179
|
$c->log->warn( '* $c->stash->{current_model_instance} # the instance of the model to use for this request' ); |
891
|
46
|
|
|
|
|
588
|
$c->log->warn( 'NB: in version 5.81, the "random" behavior will not work at all.' ); |
892
|
46
|
|
|
|
|
114
|
} |
893
|
46
|
100
|
|
|
|
232
|
|
894
|
16
|
|
|
|
|
30
|
return $c->_filter_component( $comp ); |
|
16
|
|
|
|
|
53
|
|
895
|
0
|
0
|
|
|
|
0
|
} |
896
|
0
|
|
|
|
|
0
|
|
897
|
0
|
0
|
|
|
|
0
|
|
898
|
|
|
|
|
|
|
=head2 $c->view($name) |
899
|
|
|
|
|
|
|
|
900
|
19
|
|
|
|
|
106
|
Gets a L<Catalyst::View> instance by name. |
901
|
19
|
100
|
|
|
|
61
|
|
|
6
|
|
|
|
|
15
|
|
902
|
14
|
|
|
|
|
42
|
$c->view('Foo')->do_stuff; |
903
|
|
|
|
|
|
|
|
904
|
|
|
|
|
|
|
Any extra arguments are directly passed to ACCEPT_CONTEXT. |
905
|
2
|
50
|
|
|
|
6
|
|
906
|
|
|
|
|
|
|
If the name is omitted, it will look for |
907
|
0
|
0
|
|
|
|
0
|
- a view object in $c->stash->{current_view_instance}, then |
908
|
|
|
|
|
|
|
- a view name in $c->stash->{current_view}, then |
909
|
0
|
0
|
|
|
|
0
|
- a config setting 'default_view', or |
910
|
|
|
|
|
|
|
- check if there is only one view, and return it if that's the case. |
911
|
|
|
|
|
|
|
|
912
|
2
|
100
|
|
|
|
10
|
If you want to search for views, pass in a regexp as the argument. |
913
|
|
|
|
|
|
|
|
914
|
1
|
|
|
|
|
4
|
# find all views that start with Foo |
915
|
|
|
|
|
|
|
my @foo_views = $c->view(qr{^Foo}); |
916
|
1
|
50
|
|
|
|
5
|
|
917
|
1
|
|
|
|
|
4
|
=cut |
918
|
1
|
|
|
|
|
9
|
|
919
|
1
|
|
|
|
|
5
|
my ( $c, $name, @args ) = @_; |
920
|
1
|
|
|
|
|
6
|
|
921
|
1
|
|
|
|
|
4
|
my $appclass = ref($c) || $c; |
922
|
|
|
|
|
|
|
if( $name ) { |
923
|
|
|
|
|
|
|
unless ( $name->$_isa('Regexp') ) { # Direct component hash lookup to avoid costly regexps |
924
|
1
|
|
|
|
|
5
|
my $comps = $c->components; |
925
|
|
|
|
|
|
|
my $check = $appclass."::View::".$name; |
926
|
|
|
|
|
|
|
if( exists $comps->{$check} ) { |
927
|
|
|
|
|
|
|
return $c->_filter_component( $comps->{$check}, @args ); |
928
|
|
|
|
|
|
|
} |
929
|
|
|
|
|
|
|
else { |
930
|
|
|
|
|
|
|
$c->log->warn( "Attempted to use view '$check', but does not exist" ); |
931
|
|
|
|
|
|
|
} |
932
|
|
|
|
|
|
|
foreach my $path (@{$appclass->config->{ setup_components }->{ search_extra }}) { |
933
|
|
|
|
|
|
|
next unless $path =~ /.*::View/; |
934
|
|
|
|
|
|
|
$check = $path."::".$name; |
935
|
|
|
|
|
|
|
return $c->_filter_component( $comps->{$check}, @args ) if exists $comps->{$check}; |
936
|
|
|
|
|
|
|
} |
937
|
|
|
|
|
|
|
} |
938
|
|
|
|
|
|
|
my @result = $c->_comp_search_prefixes( $name, qw/View V/ ); |
939
|
|
|
|
|
|
|
return map { $c->_filter_component( $_, @args ) } @result if ref $name; |
940
|
|
|
|
|
|
|
return $c->_filter_component( $result[ 0 ], @args ); |
941
|
|
|
|
|
|
|
} |
942
|
|
|
|
|
|
|
|
943
|
|
|
|
|
|
|
if (ref $c) { |
944
|
|
|
|
|
|
|
return $c->stash->{current_view_instance} |
945
|
|
|
|
|
|
|
if $c->stash->{current_view_instance}; |
946
|
|
|
|
|
|
|
return $c->view( $c->stash->{current_view} ) |
947
|
|
|
|
|
|
|
if $c->stash->{current_view}; |
948
|
|
|
|
|
|
|
} |
949
|
|
|
|
|
|
|
return $c->view( $appclass->config->{default_view} ) |
950
|
33
|
|
|
33
|
1
|
2083
|
if $appclass->config->{default_view}; |
951
|
|
|
|
|
|
|
|
952
|
33
|
|
66
|
|
|
144
|
my( $comp, $rest ) = $c->_comp_search_prefixes( undef, qw/View V/); |
953
|
33
|
100
|
|
|
|
101
|
|
954
|
29
|
100
|
|
|
|
133
|
if( $rest ) { |
955
|
26
|
|
|
|
|
327
|
$c->log->warn( 'Calling $c->view() will return a random view unless you specify one of:' ); |
956
|
26
|
|
|
|
|
98
|
$c->log->warn( '* $c->config(default_view => "the name of the default view to use")' ); |
957
|
26
|
100
|
|
|
|
78
|
$c->log->warn( '* $c->stash->{current_view} # the name of the view to use for this request' ); |
958
|
14
|
|
|
|
|
57
|
$c->log->warn( '* $c->stash->{current_view_instance} # the instance of the view to use for this request' ); |
959
|
|
|
|
|
|
|
$c->log->warn( 'NB: in version 5.81, the "random" behavior will not work at all.' ); |
960
|
|
|
|
|
|
|
} |
961
|
12
|
|
|
|
|
46
|
|
962
|
|
|
|
|
|
|
return $c->_filter_component( $comp ); |
963
|
12
|
|
|
|
|
33
|
} |
|
12
|
|
|
|
|
48
|
|
964
|
0
|
0
|
|
|
|
0
|
|
965
|
0
|
|
|
|
|
0
|
=head2 $c->controllers |
966
|
0
|
0
|
|
|
|
0
|
|
967
|
|
|
|
|
|
|
Returns the available names which can be passed to $c->controller |
968
|
|
|
|
|
|
|
|
969
|
15
|
|
|
|
|
123
|
=cut |
970
|
15
|
100
|
|
|
|
61
|
|
|
4
|
|
|
|
|
12
|
|
971
|
12
|
|
|
|
|
43
|
my ( $c ) = @_; |
972
|
|
|
|
|
|
|
return $c->_comp_names(qw/Controller C/); |
973
|
|
|
|
|
|
|
} |
974
|
4
|
100
|
|
|
|
17
|
|
975
|
|
|
|
|
|
|
=head2 $c->models |
976
|
2
|
50
|
|
|
|
9
|
|
977
|
|
|
|
|
|
|
Returns the available names which can be passed to $c->model |
978
|
2
|
50
|
|
|
|
10
|
|
979
|
|
|
|
|
|
|
=cut |
980
|
|
|
|
|
|
|
|
981
|
4
|
100
|
|
|
|
16
|
my ( $c ) = @_; |
982
|
|
|
|
|
|
|
return $c->_comp_names(qw/Model M/); |
983
|
2
|
|
|
|
|
9
|
} |
984
|
|
|
|
|
|
|
|
985
|
2
|
100
|
|
|
|
27
|
|
986
|
1
|
|
|
|
|
4
|
=head2 $c->views |
987
|
1
|
|
|
|
|
8
|
|
988
|
1
|
|
|
|
|
5
|
Returns the available names which can be passed to $c->view |
989
|
1
|
|
|
|
|
5
|
|
990
|
1
|
|
|
|
|
8
|
=cut |
991
|
|
|
|
|
|
|
|
992
|
|
|
|
|
|
|
my ( $c ) = @_; |
993
|
2
|
|
|
|
|
10
|
return $c->_comp_names(qw/View V/); |
994
|
|
|
|
|
|
|
} |
995
|
|
|
|
|
|
|
|
996
|
|
|
|
|
|
|
=head2 $c->comp($name) |
997
|
|
|
|
|
|
|
|
998
|
|
|
|
|
|
|
=head2 $c->component($name) |
999
|
|
|
|
|
|
|
|
1000
|
|
|
|
|
|
|
Gets a component object by name. This method is not recommended, |
1001
|
|
|
|
|
|
|
unless you want to get a specific component by full |
1002
|
|
|
|
|
|
|
class. C<< $c->controller >>, C<< $c->model >>, and C<< $c->view >> |
1003
|
1
|
|
|
1
|
1
|
6
|
should be used instead. |
1004
|
1
|
|
|
|
|
8
|
|
1005
|
|
|
|
|
|
|
If C<$name> is a regexp, a list of components matched against the full |
1006
|
|
|
|
|
|
|
component name will be returned. |
1007
|
|
|
|
|
|
|
|
1008
|
|
|
|
|
|
|
If Catalyst can't find a component by name, it will fallback to regex |
1009
|
|
|
|
|
|
|
matching by default. To disable this behaviour set |
1010
|
|
|
|
|
|
|
disable_component_resolution_regex_fallback to a true value. |
1011
|
|
|
|
|
|
|
|
1012
|
|
|
|
|
|
|
__PACKAGE__->config( disable_component_resolution_regex_fallback => 1 ); |
1013
|
|
|
|
|
|
|
|
1014
|
1
|
|
|
1
|
1
|
4
|
=cut |
1015
|
1
|
|
|
|
|
4
|
|
1016
|
|
|
|
|
|
|
my ( $c, $name, @args ) = @_; |
1017
|
|
|
|
|
|
|
|
1018
|
|
|
|
|
|
|
if( $name ) { |
1019
|
|
|
|
|
|
|
my $comps = $c->components; |
1020
|
|
|
|
|
|
|
|
1021
|
|
|
|
|
|
|
if( !ref $name ) { |
1022
|
|
|
|
|
|
|
# is it the exact name? |
1023
|
|
|
|
|
|
|
return $c->_filter_component( $comps->{ $name }, @args ) |
1024
|
|
|
|
|
|
|
if exists $comps->{ $name }; |
1025
|
|
|
|
|
|
|
|
1026
|
1
|
|
|
1
|
1
|
384
|
# perhaps we just omitted "MyApp"? |
1027
|
1
|
|
|
|
|
7
|
my $composed = ( ref $c || $c ) . "::${name}"; |
1028
|
|
|
|
|
|
|
return $c->_filter_component( $comps->{ $composed }, @args ) |
1029
|
|
|
|
|
|
|
if exists $comps->{ $composed }; |
1030
|
|
|
|
|
|
|
|
1031
|
|
|
|
|
|
|
# search all of the models, views and controllers |
1032
|
|
|
|
|
|
|
my( $comp ) = $c->_comp_search_prefixes( $name, qw/Model M Controller C View V/ ); |
1033
|
|
|
|
|
|
|
return $c->_filter_component( $comp, @args ) if $comp; |
1034
|
|
|
|
|
|
|
} |
1035
|
|
|
|
|
|
|
|
1036
|
|
|
|
|
|
|
return |
1037
|
|
|
|
|
|
|
if $c->config->{disable_component_resolution_regex_fallback}; |
1038
|
|
|
|
|
|
|
|
1039
|
|
|
|
|
|
|
# This is here so $c->comp( '::M::' ) works |
1040
|
|
|
|
|
|
|
my $query = ref $name ? $name : qr{$name}i; |
1041
|
|
|
|
|
|
|
|
1042
|
|
|
|
|
|
|
my @result = grep { m{$query} } keys %{ $c->components }; |
1043
|
|
|
|
|
|
|
return map { $c->_filter_component( $_, @args ) } @result if ref $name; |
1044
|
|
|
|
|
|
|
|
1045
|
|
|
|
|
|
|
if( $result[ 0 ] ) { |
1046
|
|
|
|
|
|
|
$c->log->warn( Carp::shortmess(qq(Found results for "${name}" using regexp fallback)) ); |
1047
|
|
|
|
|
|
|
$c->log->warn( 'Relying on the regexp fallback behavior for component resolution' ); |
1048
|
|
|
|
|
|
|
$c->log->warn( 'is unreliable and unsafe. You have been warned' ); |
1049
|
|
|
|
|
|
|
return $c->_filter_component( $result[ 0 ], @args ); |
1050
|
|
|
|
|
|
|
} |
1051
|
16426
|
|
|
16426
|
1
|
79180
|
|
1052
|
|
|
|
|
|
|
# I would expect to return an empty list here, but that breaks back-compat |
1053
|
16426
|
100
|
|
|
|
33690
|
} |
1054
|
16425
|
|
|
|
|
43814
|
|
1055
|
|
|
|
|
|
|
# fallback |
1056
|
16425
|
100
|
|
|
|
35100
|
return sort keys %{ $c->components }; |
1057
|
|
|
|
|
|
|
} |
1058
|
|
|
|
|
|
|
|
1059
|
16420
|
100
|
|
|
|
55440
|
=head2 CLASS DATA AND HELPER CLASSES |
1060
|
|
|
|
|
|
|
|
1061
|
|
|
|
|
|
|
=head2 $c->config |
1062
|
30
|
|
66
|
|
|
158
|
|
1063
|
|
|
|
|
|
|
Returns or takes a hashref containing the application's configuration. |
1064
|
30
|
100
|
|
|
|
130
|
|
1065
|
|
|
|
|
|
|
__PACKAGE__->config( { db => 'dsn:SQLite:foo.db' } ); |
1066
|
|
|
|
|
|
|
|
1067
|
12
|
|
|
|
|
85
|
You can also use a C<YAML>, C<XML> or L<Config::General> config file |
1068
|
12
|
100
|
|
|
|
71
|
like C<myapp.conf> in your applications home directory. See |
1069
|
|
|
|
|
|
|
L<Catalyst::Plugin::ConfigLoader>. |
1070
|
|
|
|
|
|
|
|
1071
|
|
|
|
|
|
|
=head3 Cascading configuration |
1072
|
7
|
50
|
|
|
|
27
|
|
1073
|
|
|
|
|
|
|
The config method is present on all Catalyst components, and configuration |
1074
|
|
|
|
|
|
|
will be merged when an application is started. Configuration loaded with |
1075
|
7
|
100
|
|
|
|
55
|
L<Catalyst::Plugin::ConfigLoader> takes precedence over other configuration, |
1076
|
|
|
|
|
|
|
followed by configuration in your top level C<MyApp> class. These two |
1077
|
7
|
|
|
|
|
15
|
configurations are merged, and then configuration data whose hash key matches a |
|
108
|
|
|
|
|
326
|
|
|
7
|
|
|
|
|
20
|
|
1078
|
7
|
100
|
|
|
|
41
|
component name is merged with configuration for that component. |
|
3
|
|
|
|
|
10
|
|
1079
|
|
|
|
|
|
|
|
1080
|
2
|
50
|
|
|
|
9
|
The configuration for a component is then passed to the C<new> method when a |
1081
|
0
|
|
|
|
|
0
|
component is constructed. |
1082
|
0
|
|
|
|
|
0
|
|
1083
|
0
|
|
|
|
|
0
|
For example: |
1084
|
0
|
|
|
|
|
0
|
|
1085
|
|
|
|
|
|
|
MyApp->config({ 'Model::Foo' => { bar => 'baz', overrides => 'me' } }); |
1086
|
|
|
|
|
|
|
MyApp::Model::Foo->config({ quux => 'frob', overrides => 'this' }); |
1087
|
|
|
|
|
|
|
|
1088
|
|
|
|
|
|
|
will mean that C<MyApp::Model::Foo> receives the following data when |
1089
|
|
|
|
|
|
|
constructed: |
1090
|
|
|
|
|
|
|
|
1091
|
3
|
|
|
|
|
8
|
MyApp::Model::Foo->new({ |
|
3
|
|
|
|
|
11
|
|
1092
|
|
|
|
|
|
|
bar => 'baz', |
1093
|
|
|
|
|
|
|
quux => 'frob', |
1094
|
|
|
|
|
|
|
overrides => 'me', |
1095
|
|
|
|
|
|
|
}); |
1096
|
|
|
|
|
|
|
|
1097
|
|
|
|
|
|
|
It's common practice to use a Moose attribute |
1098
|
|
|
|
|
|
|
on the receiving component to access the config value. |
1099
|
|
|
|
|
|
|
|
1100
|
|
|
|
|
|
|
package MyApp::Model::Foo; |
1101
|
|
|
|
|
|
|
|
1102
|
|
|
|
|
|
|
use Moose; |
1103
|
|
|
|
|
|
|
|
1104
|
|
|
|
|
|
|
# this attr will receive 'baz' at construction time |
1105
|
|
|
|
|
|
|
has 'bar' => ( |
1106
|
|
|
|
|
|
|
is => 'rw', |
1107
|
|
|
|
|
|
|
isa => 'Str', |
1108
|
|
|
|
|
|
|
); |
1109
|
|
|
|
|
|
|
|
1110
|
|
|
|
|
|
|
You can then get the value 'baz' by calling $c->model('Foo')->bar |
1111
|
|
|
|
|
|
|
(or $self->bar inside code in the model). |
1112
|
|
|
|
|
|
|
|
1113
|
|
|
|
|
|
|
B<NOTE:> you MUST NOT call C<< $self->config >> or C<< __PACKAGE__->config >> |
1114
|
|
|
|
|
|
|
as a way of reading config within your code, as this B<will not> give you the |
1115
|
|
|
|
|
|
|
correctly merged config back. You B<MUST> take the config values supplied to |
1116
|
|
|
|
|
|
|
the constructor and use those instead. |
1117
|
|
|
|
|
|
|
|
1118
|
|
|
|
|
|
|
=cut |
1119
|
|
|
|
|
|
|
|
1120
|
|
|
|
|
|
|
around config => sub { |
1121
|
|
|
|
|
|
|
my $orig = shift; |
1122
|
|
|
|
|
|
|
my $c = shift; |
1123
|
|
|
|
|
|
|
|
1124
|
|
|
|
|
|
|
croak('Setting config after setup has been run is not allowed.') |
1125
|
|
|
|
|
|
|
if ( @_ and $c->setup_finished ); |
1126
|
|
|
|
|
|
|
|
1127
|
|
|
|
|
|
|
$c->$orig(@_); |
1128
|
|
|
|
|
|
|
}; |
1129
|
|
|
|
|
|
|
|
1130
|
|
|
|
|
|
|
=head2 $c->log |
1131
|
|
|
|
|
|
|
|
1132
|
|
|
|
|
|
|
Returns the logging object instance. Unless it is already set, Catalyst |
1133
|
|
|
|
|
|
|
sets this up with a L<Catalyst::Log> object. To use your own log class, |
1134
|
|
|
|
|
|
|
set the logger with the C<< __PACKAGE__->log >> method prior to calling |
1135
|
|
|
|
|
|
|
C<< __PACKAGE__->setup >>. |
1136
|
|
|
|
|
|
|
|
1137
|
|
|
|
|
|
|
__PACKAGE__->log( MyLogger->new ); |
1138
|
|
|
|
|
|
|
__PACKAGE__->setup; |
1139
|
|
|
|
|
|
|
|
1140
|
|
|
|
|
|
|
And later: |
1141
|
|
|
|
|
|
|
|
1142
|
|
|
|
|
|
|
$c->log->info( 'Now logging with my own logger!' ); |
1143
|
|
|
|
|
|
|
|
1144
|
|
|
|
|
|
|
Your log class should implement the methods described in |
1145
|
|
|
|
|
|
|
L<Catalyst::Log>. |
1146
|
|
|
|
|
|
|
|
1147
|
|
|
|
|
|
|
=head2 has_encoding |
1148
|
|
|
|
|
|
|
|
1149
|
|
|
|
|
|
|
Returned True if there's a valid encoding |
1150
|
|
|
|
|
|
|
|
1151
|
|
|
|
|
|
|
=head2 clear_encoding |
1152
|
|
|
|
|
|
|
|
1153
|
|
|
|
|
|
|
Clears the encoding for the current context |
1154
|
|
|
|
|
|
|
|
1155
|
|
|
|
|
|
|
=head2 encoding |
1156
|
|
|
|
|
|
|
|
1157
|
|
|
|
|
|
|
Sets or gets the application encoding. Setting encoding takes either an |
1158
|
|
|
|
|
|
|
Encoding object or a string that we try to resolve via L<Encode::find_encoding>. |
1159
|
|
|
|
|
|
|
|
1160
|
|
|
|
|
|
|
You would expect to get the encoding object back if you attempt to set it. If |
1161
|
|
|
|
|
|
|
there is a failure you will get undef returned and an error message in the log. |
1162
|
|
|
|
|
|
|
|
1163
|
|
|
|
|
|
|
=cut |
1164
|
|
|
|
|
|
|
|
1165
|
|
|
|
|
|
|
|
1166
|
|
|
|
|
|
|
my $c = shift; |
1167
|
|
|
|
|
|
|
if(blessed $c) { |
1168
|
|
|
|
|
|
|
$c->encoding(undef); |
1169
|
|
|
|
|
|
|
} else { |
1170
|
|
|
|
|
|
|
$c->log->error("You can't clear encoding on the application"); |
1171
|
|
|
|
|
|
|
} |
1172
|
|
|
|
|
|
|
} |
1173
|
|
|
|
|
|
|
|
1174
|
|
|
|
|
|
|
my $c = shift; |
1175
|
|
|
|
|
|
|
my $encoding; |
1176
|
|
|
|
|
|
|
|
1177
|
|
|
|
|
|
|
if ( scalar @_ ) { |
1178
|
|
|
|
|
|
|
|
1179
|
|
|
|
|
|
|
# Don't let one change this once we are too far into the response |
1180
|
|
|
|
|
|
|
if(blessed $c && $c->res->finalized_headers) { |
1181
|
|
|
|
|
|
|
Carp::croak("You may not change the encoding once the headers are finalized"); |
1182
|
|
|
|
|
|
|
return; |
1183
|
|
|
|
|
|
|
} |
1184
|
|
|
|
|
|
|
|
1185
|
|
|
|
|
|
|
# Let it be set to undef |
1186
|
|
|
|
|
|
|
if (my $wanted = shift) { |
1187
|
|
|
|
|
|
|
$encoding = Encode::find_encoding($wanted) |
1188
|
|
|
|
|
|
|
or Carp::croak( qq/Unknown encoding '$wanted'/ ); |
1189
|
|
|
|
|
|
|
binmode(STDERR, ':encoding(' . $encoding->name . ')'); |
1190
|
|
|
|
|
|
|
} |
1191
|
|
|
|
|
|
|
else { |
1192
|
|
|
|
|
|
|
binmode(STDERR); |
1193
|
|
|
|
|
|
|
} |
1194
|
|
|
|
|
|
|
|
1195
|
|
|
|
|
|
|
$encoding = ref $c |
1196
|
|
|
|
|
|
|
? $c->{encoding} = $encoding |
1197
|
|
|
|
|
|
|
: $c->_encoding($encoding); |
1198
|
|
|
|
|
|
|
} else { |
1199
|
|
|
|
|
|
|
$encoding = ref $c && exists $c->{encoding} |
1200
|
0
|
0
|
|
0
|
1
|
0
|
? $c->{encoding} |
1201
|
|
|
|
|
|
|
: $c->_encoding; |
1202
|
|
|
|
|
|
|
} |
1203
|
2
|
|
|
2
|
1
|
13
|
|
1204
|
2
|
50
|
|
|
|
12
|
return $encoding; |
1205
|
2
|
|
|
|
|
7
|
} |
1206
|
|
|
|
|
|
|
|
1207
|
0
|
|
|
|
|
0
|
=head2 $c->debug |
1208
|
|
|
|
|
|
|
|
1209
|
|
|
|
|
|
|
Returns 1 if debug mode is enabled, 0 otherwise. |
1210
|
|
|
|
|
|
|
|
1211
|
|
|
|
|
|
|
You can enable debug mode in several ways: |
1212
|
4921
|
|
|
4921
|
1
|
50996
|
|
1213
|
4921
|
|
|
|
|
7814
|
=over |
1214
|
|
|
|
|
|
|
|
1215
|
4921
|
100
|
|
|
|
11359
|
=item By calling myapp_server.pl with the -d flag |
1216
|
|
|
|
|
|
|
|
1217
|
|
|
|
|
|
|
=item With the environment variables MYAPP_DEBUG, or CATALYST_DEBUG |
1218
|
173
|
100
|
100
|
|
|
1206
|
|
1219
|
1
|
|
|
|
|
181
|
=item The -Debug option in your MyApp.pm |
1220
|
0
|
|
|
|
|
0
|
|
1221
|
|
|
|
|
|
|
=item By declaring C<sub debug { 1 }> in your MyApp.pm. |
1222
|
|
|
|
|
|
|
|
1223
|
|
|
|
|
|
|
=back |
1224
|
172
|
100
|
|
|
|
825
|
|
1225
|
168
|
50
|
|
|
|
1220
|
The first three also set the log level to 'debug'. |
1226
|
|
|
|
|
|
|
|
1227
|
168
|
|
|
184
|
|
38775
|
Calling C<< $c->debug(1) >> has no effect. |
|
151
|
|
|
|
|
7202
|
|
|
151
|
|
|
|
|
378
|
|
|
151
|
|
|
|
|
1236
|
|
1228
|
|
|
|
|
|
|
|
1229
|
|
|
|
|
|
|
=cut |
1230
|
4
|
|
|
|
|
30
|
|
1231
|
|
|
|
|
|
|
|
1232
|
|
|
|
|
|
|
=head2 $c->dispatcher |
1233
|
|
|
|
|
|
|
|
1234
|
172
|
100
|
|
|
|
156602
|
Returns the dispatcher instance. See L<Catalyst::Dispatcher>. |
1235
|
|
|
|
|
|
|
|
1236
|
|
|
|
|
|
|
=head2 $c->engine |
1237
|
|
|
|
|
|
|
|
1238
|
|
|
|
|
|
|
Returns the engine instance. See L<Catalyst::Engine>. |
1239
|
4748
|
100
|
66
|
|
|
28383
|
|
1240
|
|
|
|
|
|
|
|
1241
|
|
|
|
|
|
|
=head2 UTILITY METHODS |
1242
|
4920
|
|
|
|
|
50833
|
|
1243
|
|
|
|
|
|
|
=head2 $c->path_to(@path) |
1244
|
|
|
|
|
|
|
|
1245
|
|
|
|
|
|
|
Merges C<@path> with C<< $c->config->{home} >> and returns a |
1246
|
|
|
|
|
|
|
L<Path::Class::Dir> object. Note you can usually use this object as |
1247
|
|
|
|
|
|
|
a filename, but sometimes you will have to explicitly stringify it |
1248
|
|
|
|
|
|
|
yourself by calling the C<< ->stringify >> method. |
1249
|
|
|
|
|
|
|
|
1250
|
|
|
|
|
|
|
For example: |
1251
|
|
|
|
|
|
|
|
1252
|
|
|
|
|
|
|
$c->path_to( 'db', 'sqlite.db' ); |
1253
|
|
|
|
|
|
|
|
1254
|
|
|
|
|
|
|
=cut |
1255
|
|
|
|
|
|
|
|
1256
|
|
|
|
|
|
|
my ( $c, @path ) = @_; |
1257
|
|
|
|
|
|
|
my $path = Path::Class::Dir->new( $c->config->{home}, @path ); |
1258
|
|
|
|
|
|
|
if ( -d $path ) { return $path } |
1259
|
|
|
|
|
|
|
else { return Path::Class::File->new( $c->config->{home}, @path ) } |
1260
|
|
|
|
|
|
|
} |
1261
|
|
|
|
|
|
|
|
1262
|
|
|
|
|
|
|
my ( $class, $name, $plugin, @args ) = @_; |
1263
|
|
|
|
|
|
|
|
1264
|
|
|
|
|
|
|
# See block comment in t/unit_core_plugin.t |
1265
|
|
|
|
|
|
|
$class->log->warn(qq/Adding plugin using the ->plugin method is deprecated, and will be removed in a future release/); |
1266
|
|
|
|
|
|
|
|
1267
|
|
|
|
|
|
|
$class->_register_plugin( $plugin, 1 ); |
1268
|
|
|
|
|
|
|
|
1269
|
7222
|
|
|
7222
|
1
|
130460
|
eval { $plugin->import }; |
1270
|
|
|
|
|
|
|
$class->mk_classdata($name); |
1271
|
|
|
|
|
|
|
my $obj; |
1272
|
|
|
|
|
|
|
eval { $obj = $plugin->new(@args) }; |
1273
|
|
|
|
|
|
|
|
1274
|
|
|
|
|
|
|
if ($@) { |
1275
|
|
|
|
|
|
|
Catalyst::Exception->throw( message => |
1276
|
|
|
|
|
|
|
qq/Couldn't instantiate instant plugin "$plugin", "$@"/ ); |
1277
|
|
|
|
|
|
|
} |
1278
|
|
|
|
|
|
|
|
1279
|
|
|
|
|
|
|
$class->$name($obj); |
1280
|
|
|
|
|
|
|
$class->log->debug(qq/Initialized instant plugin "$plugin" as "$name"/) |
1281
|
|
|
|
|
|
|
if $class->debug; |
1282
|
|
|
|
|
|
|
} |
1283
|
|
|
|
|
|
|
|
1284
|
|
|
|
|
|
|
=head2 MyApp->setup |
1285
|
|
|
|
|
|
|
|
1286
|
|
|
|
|
|
|
Initializes the dispatcher and engine, loads any plugins, and loads the |
1287
|
|
|
|
|
|
|
model, view, and controller components. You may also specify an array |
1288
|
|
|
|
|
|
|
of plugins to load here, if you choose to not load them in the C<use |
1289
|
|
|
|
|
|
|
Catalyst> line. |
1290
|
|
|
|
|
|
|
|
1291
|
|
|
|
|
|
|
MyApp->setup; |
1292
|
|
|
|
|
|
|
MyApp->setup( qw/-Debug/ ); |
1293
|
|
|
|
|
|
|
|
1294
|
|
|
|
|
|
|
B<Note:> You B<should not> wrap this method with method modifiers |
1295
|
|
|
|
|
|
|
or bad things will happen - wrap the C<setup_finalize> method instead. |
1296
|
18
|
|
|
18
|
1
|
14931
|
|
1297
|
18
|
|
|
|
|
112
|
B<Note:> You can create a custom setup stage that will execute when the |
1298
|
18
|
100
|
|
|
|
1402
|
application is starting. Use this to customize setup. |
|
7
|
|
|
|
|
334
|
|
1299
|
11
|
|
|
|
|
628
|
|
1300
|
|
|
|
|
|
|
MyApp->setup(-Custom=value); |
1301
|
|
|
|
|
|
|
|
1302
|
|
|
|
|
|
|
sub setup_custom { |
1303
|
1
|
|
|
1
|
0
|
467
|
my ($class, $value) = @_; |
1304
|
|
|
|
|
|
|
} |
1305
|
|
|
|
|
|
|
|
1306
|
1
|
|
|
|
|
5
|
Can be handy if you want to hook into the setup phase. |
1307
|
|
|
|
|
|
|
|
1308
|
1
|
|
|
|
|
15
|
=cut |
1309
|
|
|
|
|
|
|
|
1310
|
1
|
|
|
|
|
2
|
my ( $class, @arguments ) = @_; |
|
1
|
|
|
|
|
7
|
|
1311
|
1
|
|
|
|
|
9
|
croak('Running setup more than once') |
1312
|
1
|
|
|
|
|
2
|
if ( $class->setup_finished ); |
1313
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
7
|
|
1314
|
|
|
|
|
|
|
unless ( $class->isa('Catalyst') ) { |
1315
|
1
|
50
|
|
|
|
18
|
|
1316
|
0
|
|
|
|
|
0
|
Catalyst::Exception->throw( |
1317
|
|
|
|
|
|
|
message => qq/'$class' does not inherit from Catalyst/ ); |
1318
|
|
|
|
|
|
|
} |
1319
|
|
|
|
|
|
|
|
1320
|
1
|
|
|
|
|
7
|
if ( $class->arguments ) { |
1321
|
1
|
50
|
|
|
|
4
|
@arguments = ( @arguments, @{ $class->arguments } ); |
1322
|
|
|
|
|
|
|
} |
1323
|
|
|
|
|
|
|
|
1324
|
|
|
|
|
|
|
# Process options |
1325
|
|
|
|
|
|
|
my $flags = {}; |
1326
|
|
|
|
|
|
|
|
1327
|
|
|
|
|
|
|
foreach (@arguments) { |
1328
|
|
|
|
|
|
|
|
1329
|
|
|
|
|
|
|
if (/^-Debug$/) { |
1330
|
|
|
|
|
|
|
$flags->{log} = |
1331
|
|
|
|
|
|
|
( $flags->{log} ) ? 'debug,' . $flags->{log} : 'debug'; |
1332
|
|
|
|
|
|
|
} |
1333
|
|
|
|
|
|
|
elsif (/^-(\w+)=?(.*)$/) { |
1334
|
|
|
|
|
|
|
$flags->{ lc $1 } = $2; |
1335
|
|
|
|
|
|
|
} |
1336
|
|
|
|
|
|
|
else { |
1337
|
|
|
|
|
|
|
push @{ $flags->{plugins} }, $_; |
1338
|
|
|
|
|
|
|
} |
1339
|
|
|
|
|
|
|
} |
1340
|
|
|
|
|
|
|
|
1341
|
|
|
|
|
|
|
$class->setup_home( delete $flags->{home} ); |
1342
|
|
|
|
|
|
|
|
1343
|
|
|
|
|
|
|
$class->setup_log( delete $flags->{log} ); |
1344
|
|
|
|
|
|
|
$class->setup_plugins( delete $flags->{plugins} ); |
1345
|
|
|
|
|
|
|
|
1346
|
|
|
|
|
|
|
$class->setup_data_handlers(); |
1347
|
|
|
|
|
|
|
$class->setup_dispatcher( delete $flags->{dispatcher} ); |
1348
|
|
|
|
|
|
|
if (my $engine = delete $flags->{engine}) { |
1349
|
|
|
|
|
|
|
$class->log->warn("Specifying the engine in ->setup is no longer supported, see Catalyst::Upgrading"); |
1350
|
|
|
|
|
|
|
} |
1351
|
|
|
|
|
|
|
$class->setup_engine(); |
1352
|
163
|
|
|
163
|
1
|
226270
|
$class->setup_stats( delete $flags->{stats} ); |
1353
|
163
|
50
|
|
|
|
968
|
|
1354
|
|
|
|
|
|
|
for my $flag ( sort keys %{$flags} ) { |
1355
|
|
|
|
|
|
|
|
1356
|
163
|
50
|
|
|
|
1359
|
if ( my $code = $class->can( 'setup_' . $flag ) ) { |
1357
|
|
|
|
|
|
|
&$code( $class, delete $flags->{$flag} ); |
1358
|
0
|
|
|
|
|
0
|
} |
1359
|
|
|
|
|
|
|
else { |
1360
|
|
|
|
|
|
|
$class->log->warn(qq/Unknown flag "$flag"/); |
1361
|
|
|
|
|
|
|
} |
1362
|
163
|
100
|
|
|
|
889
|
} |
1363
|
157
|
|
|
|
|
527
|
|
|
157
|
|
|
|
|
684
|
|
1364
|
|
|
|
|
|
|
eval { require Catalyst::Devel; }; |
1365
|
|
|
|
|
|
|
if( !$@ && $ENV{CATALYST_SCRIPT_GEN} && ( $ENV{CATALYST_SCRIPT_GEN} < $Catalyst::Devel::CATALYST_SCRIPT_GEN ) ) { |
1366
|
|
|
|
|
|
|
$class->log->warn(<<"EOF"); |
1367
|
163
|
|
|
|
|
597
|
You are running an old script! |
1368
|
|
|
|
|
|
|
|
1369
|
163
|
|
|
|
|
604
|
Please update by running (this will overwrite existing files): |
1370
|
|
|
|
|
|
|
catalyst.pl -force -scripts $class |
1371
|
655
|
100
|
|
|
|
1715
|
|
|
|
100
|
|
|
|
|
|
1372
|
|
|
|
|
|
|
or (this will not overwrite existing files): |
1373
|
3
|
50
|
|
|
|
15
|
catalyst.pl -scripts $class |
1374
|
|
|
|
|
|
|
|
1375
|
|
|
|
|
|
|
EOF |
1376
|
9
|
|
|
|
|
71
|
} |
1377
|
|
|
|
|
|
|
|
1378
|
|
|
|
|
|
|
# Call plugins setup, this is stupid and evil. |
1379
|
643
|
|
|
|
|
887
|
# Also screws C3 badly on 5.10, hack to avoid. |
|
643
|
|
|
|
|
1451
|
|
1380
|
|
|
|
|
|
|
{ |
1381
|
|
|
|
|
|
|
no warnings qw/redefine/; |
1382
|
|
|
|
|
|
|
local *setup = sub { }; |
1383
|
163
|
|
|
|
|
1107
|
$class->setup unless $Catalyst::__AM_RESTARTING; |
1384
|
|
|
|
|
|
|
} |
1385
|
163
|
|
|
|
|
2115
|
|
1386
|
163
|
|
|
|
|
1569
|
# If you are expecting configuration info as part of your setup, it needs |
1387
|
|
|
|
|
|
|
# to get called here and below, since we need the above line to support |
1388
|
163
|
|
|
|
|
495934
|
# ConfigLoader based configs. |
1389
|
163
|
|
|
|
|
1232
|
|
1390
|
163
|
50
|
|
|
|
49608
|
$class->setup_encoding(); |
1391
|
0
|
|
|
|
|
0
|
$class->setup_middleware(); |
1392
|
|
|
|
|
|
|
|
1393
|
163
|
|
|
|
|
1945
|
# Initialize our data structure |
1394
|
163
|
|
|
|
|
5551
|
$class->components( {} ); |
1395
|
|
|
|
|
|
|
|
1396
|
163
|
|
|
|
|
490
|
$class->setup_components; |
|
163
|
|
|
|
|
860
|
|
1397
|
|
|
|
|
|
|
|
1398
|
0
|
0
|
|
|
|
0
|
if ( $class->debug ) { |
1399
|
0
|
|
|
|
|
0
|
my @plugins = map { "$_ " . ( $_->VERSION || '' ) } $class->registered_plugins; |
1400
|
|
|
|
|
|
|
|
1401
|
|
|
|
|
|
|
if (@plugins) { |
1402
|
0
|
|
|
|
|
0
|
my $column_width = Catalyst::Utils::term_width() - 6; |
1403
|
|
|
|
|
|
|
my $t = Text::SimpleTable->new($column_width); |
1404
|
|
|
|
|
|
|
$t->row($_) for @plugins; |
1405
|
|
|
|
|
|
|
$class->log->debug( "Loaded plugins:\n" . $t->draw . "\n" ); |
1406
|
163
|
|
|
|
|
488
|
} |
|
163
|
|
|
|
|
26565
|
|
1407
|
163
|
0
|
33
|
|
|
1706
|
|
|
|
|
0
|
|
|
|
|
1408
|
0
|
|
|
|
|
0
|
my @middleware = map { |
1409
|
|
|
|
|
|
|
ref $_ eq 'CODE' ? |
1410
|
|
|
|
|
|
|
"Inline Coderef" : |
1411
|
|
|
|
|
|
|
(ref($_) .' '. ($_->can('VERSION') ? $_->VERSION || '' : '') |
1412
|
|
|
|
|
|
|
|| '') } $class->registered_middlewares; |
1413
|
|
|
|
|
|
|
|
1414
|
|
|
|
|
|
|
if (@middleware) { |
1415
|
|
|
|
|
|
|
my $column_width = Catalyst::Utils::term_width() - 6; |
1416
|
|
|
|
|
|
|
my $t = Text::SimpleTable->new($column_width); |
1417
|
|
|
|
|
|
|
$t->row($_) for @middleware; |
1418
|
|
|
|
|
|
|
$class->log->debug( "Loaded PSGI Middleware:\n" . $t->draw . "\n" ); |
1419
|
|
|
|
|
|
|
} |
1420
|
|
|
|
|
|
|
|
1421
|
|
|
|
|
|
|
my %dh = $class->registered_data_handlers; |
1422
|
|
|
|
|
|
|
if (my @data_handlers = keys %dh) { |
1423
|
164
|
|
|
164
|
|
1473
|
my $column_width = Catalyst::Utils::term_width() - 6; |
|
164
|
|
|
|
|
429
|
|
|
164
|
|
|
|
|
466926
|
|
|
163
|
|
|
|
|
441
|
|
1424
|
163
|
|
|
163
|
|
2003
|
my $t = Text::SimpleTable->new($column_width); |
1425
|
163
|
50
|
|
|
|
1876
|
$t->row($_) for @data_handlers; |
1426
|
|
|
|
|
|
|
$class->log->debug( "Loaded Request Data Handlers:\n" . $t->draw . "\n" ); |
1427
|
|
|
|
|
|
|
} |
1428
|
|
|
|
|
|
|
|
1429
|
|
|
|
|
|
|
my $dispatcher = $class->dispatcher; |
1430
|
|
|
|
|
|
|
my $engine = $class->engine; |
1431
|
|
|
|
|
|
|
my $home = $class->config->{home}; |
1432
|
163
|
|
|
|
|
1676
|
|
1433
|
163
|
|
|
|
|
1619
|
$class->log->debug(sprintf(q/Loaded dispatcher "%s"/, blessed($dispatcher))); |
1434
|
|
|
|
|
|
|
$class->log->debug(sprintf(q/Loaded engine "%s"/, blessed($engine))); |
1435
|
|
|
|
|
|
|
|
1436
|
163
|
|
|
|
|
1572
|
$home |
1437
|
|
|
|
|
|
|
? ( -d $home ) |
1438
|
163
|
|
|
|
|
1385
|
? $class->log->debug(qq/Found home "$home"/) |
1439
|
|
|
|
|
|
|
: $class->log->debug(qq/Home "$home" doesn't exist/) |
1440
|
163
|
100
|
|
|
|
2916
|
: $class->log->debug(q/Couldn't find home/); |
1441
|
7
|
|
0
|
|
|
66
|
|
|
0
|
|
|
|
|
0
|
|
1442
|
|
|
|
|
|
|
my $column_width = Catalyst::Utils::term_width() - 8 - 9; |
1443
|
7
|
50
|
|
|
|
35
|
|
1444
|
0
|
|
|
|
|
0
|
my $t = Text::SimpleTable->new( [ $column_width, 'Class' ], [ 8, 'Type' ] ); |
1445
|
0
|
|
|
|
|
0
|
for my $comp ( sort keys %{ $class->components } ) { |
1446
|
0
|
|
|
|
|
0
|
my $type = ref $class->components->{$comp} ? 'instance' : 'class'; |
1447
|
0
|
|
|
|
|
0
|
$t->row( $comp, $type ); |
1448
|
|
|
|
|
|
|
} |
1449
|
|
|
|
|
|
|
$class->log->debug( "Loaded components:\n" . $t->draw . "\n" ) |
1450
|
|
|
|
|
|
|
if ( keys %{ $class->components } ); |
1451
|
7
|
50
|
50
|
|
|
82
|
} |
|
49
|
|
|
|
|
751
|
|
1452
|
|
|
|
|
|
|
|
1453
|
|
|
|
|
|
|
# Add our self to components, since we are also a component |
1454
|
|
|
|
|
|
|
if( $class->isa('Catalyst::Controller') ){ |
1455
|
|
|
|
|
|
|
$class->components->{$class} = $class; |
1456
|
7
|
50
|
|
|
|
155
|
} |
1457
|
7
|
|
|
|
|
41
|
|
1458
|
7
|
|
|
|
|
71
|
$class->setup_actions; |
1459
|
7
|
|
|
|
|
398
|
|
1460
|
7
|
|
|
|
|
2637
|
if ( $class->debug ) { |
1461
|
|
|
|
|
|
|
my $name = $class->config->{name} || 'Application'; |
1462
|
|
|
|
|
|
|
$class->log->info("$name powered by Catalyst $Catalyst::VERSION"); |
1463
|
7
|
|
|
|
|
262
|
} |
1464
|
7
|
50
|
|
|
|
45
|
|
1465
|
7
|
|
|
|
|
41
|
if ($class->config->{case_sensitive}) { |
1466
|
7
|
|
|
|
|
35
|
$class->log->warn($class . "->config->{case_sensitive} is set."); |
1467
|
7
|
|
|
|
|
286
|
$class->log->warn("This setting is deprecated and planned to be removed in Catalyst 5.81."); |
1468
|
7
|
|
|
|
|
744
|
} |
1469
|
|
|
|
|
|
|
|
1470
|
|
|
|
|
|
|
# call these so we pre setup the composed classes |
1471
|
7
|
|
|
|
|
155
|
$class->composed_request_class; |
1472
|
7
|
|
|
|
|
36
|
$class->composed_response_class; |
1473
|
7
|
|
|
|
|
37
|
$class->composed_stats_class; |
1474
|
|
|
|
|
|
|
|
1475
|
7
|
|
|
|
|
27
|
$class->setup_finalize; |
1476
|
7
|
|
|
|
|
53
|
|
1477
|
|
|
|
|
|
|
# Flush the log for good measure (in case something turned off 'autoflush' early) |
1478
|
7
|
50
|
|
|
|
84
|
$class->log->_flush() if $class->log->can('_flush'); |
|
|
100
|
|
|
|
|
|
1479
|
|
|
|
|
|
|
|
1480
|
|
|
|
|
|
|
return $class || 1; # Just in case someone named their Application 0... |
1481
|
|
|
|
|
|
|
} |
1482
|
|
|
|
|
|
|
|
1483
|
|
|
|
|
|
|
=head2 $app->setup_finalize |
1484
|
7
|
|
|
|
|
41
|
|
1485
|
|
|
|
|
|
|
A hook to attach modifiers to. This method does not do anything except set the |
1486
|
7
|
|
|
|
|
62
|
C<setup_finished> accessor. |
1487
|
7
|
|
|
|
|
684
|
|
|
7
|
|
|
|
|
32
|
|
1488
|
5
|
50
|
|
|
|
19
|
Applying method modifiers to the C<setup> method doesn't work, because of quirky things done for plugin setup. |
1489
|
5
|
|
|
|
|
35
|
|
1490
|
|
|
|
|
|
|
Example: |
1491
|
|
|
|
|
|
|
|
1492
|
7
|
100
|
|
|
|
485
|
after setup_finalize => sub { |
|
7
|
|
|
|
|
38
|
|
1493
|
|
|
|
|
|
|
my $app = shift; |
1494
|
|
|
|
|
|
|
|
1495
|
|
|
|
|
|
|
## do stuff here.. |
1496
|
163
|
100
|
|
|
|
1242
|
}; |
1497
|
143
|
|
|
|
|
748
|
|
1498
|
|
|
|
|
|
|
=cut |
1499
|
|
|
|
|
|
|
|
1500
|
163
|
|
|
|
|
1884
|
my ($class) = @_; |
1501
|
|
|
|
|
|
|
$class->setup_finished(1); |
1502
|
162
|
100
|
|
|
|
805
|
} |
1503
|
7
|
|
100
|
|
|
54
|
|
1504
|
7
|
|
|
|
|
36
|
=head2 $c->uri_for( $path?, @args?, \%query_values?, \$fragment? ) |
1505
|
|
|
|
|
|
|
|
1506
|
|
|
|
|
|
|
=head2 $c->uri_for( $action, \@captures?, @args?, \%query_values?, \$fragment? ) |
1507
|
162
|
50
|
|
|
|
978
|
|
1508
|
0
|
|
|
|
|
0
|
=head2 $c->uri_for( $action, [@captures, @args], \%query_values?, \$fragment? ) |
1509
|
0
|
|
|
|
|
0
|
|
1510
|
|
|
|
|
|
|
Constructs an absolute L<URI> object based on the application root, the |
1511
|
|
|
|
|
|
|
provided path, and the additional arguments and query parameters provided. |
1512
|
|
|
|
|
|
|
When used as a string, provides a textual URI. If you need more flexibility |
1513
|
162
|
|
|
|
|
3414
|
than this (i.e. the option to provide relative URIs etc.) see |
1514
|
162
|
|
|
|
|
1690
|
L<Catalyst::Plugin::SmartURI>. |
1515
|
162
|
|
|
|
|
1670
|
|
1516
|
|
|
|
|
|
|
If no arguments are provided, the URI for the current action is returned. |
1517
|
162
|
|
|
|
|
1378
|
To return the current action and also provide @args, use |
1518
|
|
|
|
|
|
|
C<< $c->uri_for( $c->action, @args ) >>. |
1519
|
|
|
|
|
|
|
|
1520
|
162
|
100
|
|
|
|
1207
|
If the first argument is a string, it is taken as a public URI path relative |
1521
|
|
|
|
|
|
|
to C<< $c->namespace >> (if it doesn't begin with a forward slash) or |
1522
|
162
|
|
50
|
|
|
1813
|
relative to the application root (if it does). It is then merged with |
1523
|
|
|
|
|
|
|
C<< $c->request->base >>; any C<@args> are appended as additional path |
1524
|
|
|
|
|
|
|
components; and any C<%query_values> are appended as C<?foo=bar> parameters. |
1525
|
|
|
|
|
|
|
|
1526
|
|
|
|
|
|
|
B<NOTE> If you are using this 'stringy' first argument, we skip encoding and |
1527
|
|
|
|
|
|
|
allow you to declare something like: |
1528
|
|
|
|
|
|
|
|
1529
|
|
|
|
|
|
|
$c->uri_for('/foo/bar#baz') |
1530
|
|
|
|
|
|
|
|
1531
|
|
|
|
|
|
|
Where 'baz' is a URI fragment. We consider this first argument string to be |
1532
|
|
|
|
|
|
|
'expert' mode where you are expected to create a valid URL and we for the most |
1533
|
|
|
|
|
|
|
part just pass it through without a lot of internal effort to escape and encode. |
1534
|
|
|
|
|
|
|
|
1535
|
|
|
|
|
|
|
If the first argument is a L<Catalyst::Action> it represents an action which |
1536
|
|
|
|
|
|
|
will have its path resolved using C<< $c->dispatcher->uri_for_action >>. The |
1537
|
|
|
|
|
|
|
optional C<\@captures> argument (an arrayref) allows passing the captured |
1538
|
|
|
|
|
|
|
variables that are needed to fill in the paths of Chained and Regex actions; |
1539
|
|
|
|
|
|
|
once the path is resolved, C<uri_for> continues as though a path was |
1540
|
|
|
|
|
|
|
provided, appending any arguments or parameters and creating an absolute |
1541
|
|
|
|
|
|
|
URI. |
1542
|
|
|
|
|
|
|
|
1543
|
162
|
|
|
162
|
1
|
3105
|
The captures for the current request can be found in |
1544
|
162
|
|
|
|
|
1267
|
C<< $c->request->captures >>, and actions can be resolved using |
1545
|
|
|
|
|
|
|
C<< Catalyst::Controller->action_for($name) >>. If you have a private action |
1546
|
|
|
|
|
|
|
path, use C<< $c->uri_for_action >> instead. |
1547
|
|
|
|
|
|
|
|
1548
|
|
|
|
|
|
|
# Equivalent to $c->req->uri |
1549
|
|
|
|
|
|
|
$c->uri_for($c->action, $c->req->captures, |
1550
|
|
|
|
|
|
|
@{ $c->req->args }, $c->req->params); |
1551
|
|
|
|
|
|
|
|
1552
|
|
|
|
|
|
|
# For the Foo action in the Bar controller |
1553
|
|
|
|
|
|
|
$c->uri_for($c->controller('Bar')->action_for('Foo')); |
1554
|
|
|
|
|
|
|
|
1555
|
|
|
|
|
|
|
# Path to a static resource |
1556
|
|
|
|
|
|
|
$c->uri_for('/static/images/logo.png'); |
1557
|
|
|
|
|
|
|
|
1558
|
|
|
|
|
|
|
In general the scheme of the generated URI object will follow the incoming request |
1559
|
|
|
|
|
|
|
however if your targeted action or action chain has the Scheme attribute it will |
1560
|
|
|
|
|
|
|
use that instead. |
1561
|
|
|
|
|
|
|
|
1562
|
|
|
|
|
|
|
Also, if the targeted Action or Action chain declares Args/CaptureArgs that have |
1563
|
|
|
|
|
|
|
type constraints, we will require that your proposed URL verify on those declared |
1564
|
|
|
|
|
|
|
constraints. |
1565
|
|
|
|
|
|
|
|
1566
|
|
|
|
|
|
|
=cut |
1567
|
|
|
|
|
|
|
|
1568
|
|
|
|
|
|
|
my ( $c, $path, @args ) = @_; |
1569
|
|
|
|
|
|
|
|
1570
|
|
|
|
|
|
|
if ( $path->$_isa('Catalyst::Controller') ) { |
1571
|
|
|
|
|
|
|
$path = $path->path_prefix; |
1572
|
|
|
|
|
|
|
$path =~ s{/+\z}{}; |
1573
|
|
|
|
|
|
|
$path .= '/'; |
1574
|
|
|
|
|
|
|
} |
1575
|
|
|
|
|
|
|
|
1576
|
|
|
|
|
|
|
my $fragment = ((scalar(@args) && ref($args[-1]) eq 'SCALAR') ? ${pop @args} : undef ); |
1577
|
|
|
|
|
|
|
|
1578
|
|
|
|
|
|
|
unless(blessed $path) { |
1579
|
|
|
|
|
|
|
if (defined($path) and $path =~ s/#(.+)$//) { |
1580
|
|
|
|
|
|
|
if(defined($1) and defined $fragment) { |
1581
|
|
|
|
|
|
|
carp "Abiguious fragment declaration: You cannot define a fragment in '$path' and as an argument '$fragment'"; |
1582
|
|
|
|
|
|
|
} |
1583
|
|
|
|
|
|
|
if(defined($1)) { |
1584
|
|
|
|
|
|
|
$fragment = $1; |
1585
|
|
|
|
|
|
|
} |
1586
|
|
|
|
|
|
|
} |
1587
|
|
|
|
|
|
|
} |
1588
|
|
|
|
|
|
|
|
1589
|
|
|
|
|
|
|
my $params = |
1590
|
|
|
|
|
|
|
( scalar @args && ref $args[$#args] eq 'HASH' ? pop @args : {} ); |
1591
|
|
|
|
|
|
|
|
1592
|
|
|
|
|
|
|
undef($path) if (defined $path && $path eq ''); |
1593
|
|
|
|
|
|
|
|
1594
|
|
|
|
|
|
|
carp "uri_for called with undef argument" if grep { ! defined $_ } @args; |
1595
|
|
|
|
|
|
|
|
1596
|
|
|
|
|
|
|
my $target_action = $path->$_isa('Catalyst::Action') ? $path : undef; |
1597
|
|
|
|
|
|
|
if ( $path->$_isa('Catalyst::Action') ) { # action object |
1598
|
|
|
|
|
|
|
s|/|%2F|g for @args; |
1599
|
|
|
|
|
|
|
my $captures = [ map { s|/|%2F|g; $_; } |
1600
|
|
|
|
|
|
|
( scalar @args && ref $args[0] eq 'ARRAY' |
1601
|
|
|
|
|
|
|
? @{ shift(@args) } |
1602
|
|
|
|
|
|
|
: ()) ]; |
1603
|
|
|
|
|
|
|
|
1604
|
|
|
|
|
|
|
my $action = $path; |
1605
|
|
|
|
|
|
|
my $expanded_action = $c->dispatcher->expand_action( $action ); |
1606
|
|
|
|
|
|
|
my $num_captures = $expanded_action->number_of_captures; |
1607
|
|
|
|
|
|
|
|
1608
|
|
|
|
|
|
|
# ->uri_for( $action, \@captures_and_args, \%query_values? ) |
1609
|
|
|
|
|
|
|
if( !@args && $action->number_of_args && @$captures > $num_captures ) { |
1610
|
|
|
|
|
|
|
unshift @args, splice @$captures, $num_captures; |
1611
|
|
|
|
|
|
|
} |
1612
|
122
|
|
|
122
|
1
|
26044
|
|
1613
|
|
|
|
|
|
|
if($num_captures) { |
1614
|
122
|
100
|
|
|
|
415
|
unless($expanded_action->match_captures_constraints($c, $captures)) { |
1615
|
1
|
|
|
|
|
35
|
$c->log->debug("captures [@{$captures}] do not match the type constraints in actionchain ending with '$expanded_action'") |
1616
|
1
|
|
|
|
|
7
|
if $c->debug; |
1617
|
1
|
|
|
|
|
3
|
return undef; |
1618
|
|
|
|
|
|
|
} |
1619
|
|
|
|
|
|
|
} |
1620
|
122
|
100
|
100
|
|
|
2390
|
|
|
2
|
|
|
|
|
7
|
|
1621
|
|
|
|
|
|
|
$path = $c->dispatcher->uri_for_action($action, $captures); |
1622
|
122
|
100
|
|
|
|
414
|
if (not defined $path) { |
1623
|
47
|
100
|
100
|
|
|
255
|
$c->log->debug(qq/Can't find uri_for action '$action' @$captures/) |
1624
|
5
|
50
|
33
|
|
|
27
|
if $c->debug; |
1625
|
0
|
|
|
|
|
0
|
return undef; |
1626
|
|
|
|
|
|
|
} |
1627
|
5
|
50
|
|
|
|
13
|
$path = '/' if $path eq ''; |
1628
|
5
|
|
|
|
|
12
|
|
1629
|
|
|
|
|
|
|
# At this point @encoded_args is the remaining Args (all captures removed). |
1630
|
|
|
|
|
|
|
if($expanded_action->has_args_constraints) { |
1631
|
|
|
|
|
|
|
unless($expanded_action->match_args($c,\@args)) { |
1632
|
|
|
|
|
|
|
$c->log->debug("args [@args] do not match the type constraints in action '$expanded_action'") |
1633
|
122
|
100
|
100
|
|
|
577
|
if $c->debug; |
1634
|
|
|
|
|
|
|
return undef; |
1635
|
|
|
|
|
|
|
} |
1636
|
122
|
100
|
100
|
|
|
627
|
} |
1637
|
|
|
|
|
|
|
} |
1638
|
122
|
50
|
|
|
|
333
|
|
|
127
|
|
|
|
|
333
|
|
1639
|
|
|
|
|
|
|
unshift(@args, $path); |
1640
|
122
|
100
|
|
|
|
305
|
|
1641
|
122
|
100
|
|
|
|
1372
|
unless (defined $path && $path =~ s!^/!!) { # in-place strip |
1642
|
73
|
|
|
|
|
1003
|
my $namespace = $c->namespace; |
1643
|
123
|
|
|
|
|
224
|
if (defined $path) { # cheesy hack to handle path '../foo' |
|
123
|
|
|
|
|
281
|
|
1644
|
|
|
|
|
|
|
$namespace =~ s{(?:^|/)[^/]+$}{} while $args[0] =~ s{^\.\./}{}; |
1645
|
73
|
100
|
100
|
|
|
370
|
} |
|
53
|
|
|
|
|
130
|
|
1646
|
|
|
|
|
|
|
unshift(@args, $namespace || ''); |
1647
|
|
|
|
|
|
|
} |
1648
|
73
|
|
|
|
|
159
|
|
1649
|
73
|
|
|
|
|
252
|
# join args with '/', or a blank string |
1650
|
73
|
|
|
|
|
777
|
my $args = join('/', grep { defined($_) } @args); |
1651
|
|
|
|
|
|
|
$args =~ s/\?/%3F/g; # STUPID STUPID SPECIAL CASE |
1652
|
|
|
|
|
|
|
$args =~ s!^/+!!; |
1653
|
73
|
100
|
100
|
|
|
1397
|
|
|
|
|
100
|
|
|
|
|
1654
|
22
|
|
|
|
|
75
|
my ($base, $class) = ('/', 'URI::_generic'); |
1655
|
|
|
|
|
|
|
if(blessed($c)) { |
1656
|
|
|
|
|
|
|
$base = $c->req->base; |
1657
|
73
|
100
|
|
|
|
205
|
if($target_action) { |
1658
|
47
|
100
|
|
|
|
176
|
$target_action = $c->dispatcher->expand_action($target_action); |
1659
|
3
|
50
|
|
|
|
91
|
if(my $s = $target_action->scheme) { |
|
0
|
|
|
|
|
0
|
|
1660
|
|
|
|
|
|
|
$s = lc($s); |
1661
|
3
|
|
|
|
|
94
|
$class = "URI::$s"; |
1662
|
|
|
|
|
|
|
$base->scheme($s); |
1663
|
|
|
|
|
|
|
} else { |
1664
|
|
|
|
|
|
|
$class = ref($base); |
1665
|
70
|
|
|
|
|
290
|
} |
1666
|
70
|
100
|
|
|
|
363
|
} else { |
1667
|
3
|
50
|
|
|
|
14
|
$class = ref($base); |
1668
|
|
|
|
|
|
|
} |
1669
|
3
|
|
|
|
|
70
|
|
1670
|
|
|
|
|
|
|
$base =~ s{(?<!/)$}{/}; |
1671
|
67
|
50
|
|
|
|
172
|
} |
1672
|
|
|
|
|
|
|
|
1673
|
|
|
|
|
|
|
my $query = ''; |
1674
|
67
|
100
|
|
|
|
2627
|
if (my @keys = keys %$params) { |
1675
|
10
|
100
|
|
|
|
41
|
# somewhat lifted from URI::_query's query_form |
1676
|
3
|
50
|
|
|
|
71
|
$query = '?'.join('&', map { |
1677
|
|
|
|
|
|
|
my $val = $params->{$_}; |
1678
|
3
|
|
|
|
|
47
|
my $key = encode_utf8($_); |
1679
|
|
|
|
|
|
|
# using the URI::Escape pattern here so utf8 chars survive |
1680
|
|
|
|
|
|
|
$key =~ s/([^A-Za-z0-9\-_.!~*'() ])/$URI::Escape::escapes{$1}/go; |
1681
|
|
|
|
|
|
|
$key =~ s/ /+/g; |
1682
|
|
|
|
|
|
|
|
1683
|
113
|
|
|
|
|
630
|
$val = '' unless defined $val; |
1684
|
|
|
|
|
|
|
(map { |
1685
|
113
|
100
|
100
|
|
|
754
|
my $param = encode_utf8($_); |
1686
|
18
|
|
|
|
|
574
|
# using the URI::Escape pattern here so utf8 chars survive |
1687
|
18
|
100
|
|
|
|
49
|
$param =~ s/([^A-Za-z0-9\-_.!~*'() ])/$URI::Escape::escapes{$1}/go; |
1688
|
16
|
|
|
|
|
53
|
$param =~ s/ /+/g; |
1689
|
|
|
|
|
|
|
|
1690
|
18
|
|
100
|
|
|
68
|
"${key}=$param"; |
1691
|
|
|
|
|
|
|
} ( ref $val eq 'ARRAY' ? @$val : $val )); |
1692
|
|
|
|
|
|
|
} @keys); |
1693
|
|
|
|
|
|
|
} |
1694
|
113
|
|
|
|
|
515
|
|
|
226
|
|
|
|
|
627
|
|
1695
|
113
|
|
|
|
|
318
|
$base = encode_utf8 $base; |
1696
|
113
|
|
|
|
|
405
|
$base =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go; |
1697
|
|
|
|
|
|
|
$args = encode_utf8 $args; |
1698
|
113
|
|
|
|
|
271
|
$args =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go; |
1699
|
113
|
100
|
|
|
|
429
|
|
1700
|
104
|
|
|
|
|
327
|
if(defined $fragment) { |
1701
|
104
|
100
|
|
|
|
346
|
if(blessed $path) { |
1702
|
61
|
|
|
|
|
226
|
$fragment = encode_utf8($fragment); |
1703
|
61
|
100
|
|
|
|
277
|
$fragment =~ s/([^A-Za-z0-9\-_.!~*'() ])/$URI::Escape::escapes{$1}/go; |
1704
|
3
|
|
|
|
|
7
|
$fragment =~ s/ /+/g; |
1705
|
3
|
|
|
|
|
7
|
} |
1706
|
3
|
|
|
|
|
12
|
$query .= "#$fragment"; |
1707
|
|
|
|
|
|
|
} |
1708
|
58
|
|
|
|
|
157
|
|
1709
|
|
|
|
|
|
|
my $res = bless(\"${base}${args}${query}", $class); |
1710
|
|
|
|
|
|
|
$res; |
1711
|
43
|
|
|
|
|
97
|
} |
1712
|
|
|
|
|
|
|
|
1713
|
|
|
|
|
|
|
=head2 $c->uri_for_action( $path, \@captures_and_args?, @args?, \%query_values? ) |
1714
|
104
|
|
|
|
|
962
|
|
1715
|
|
|
|
|
|
|
=head2 $c->uri_for_action( $action, \@captures_and_args?, @args?, \%query_values? ) |
1716
|
|
|
|
|
|
|
|
1717
|
113
|
|
|
|
|
1026
|
=over |
1718
|
113
|
100
|
|
|
|
438
|
|
1719
|
|
|
|
|
|
|
=item $path |
1720
|
|
|
|
|
|
|
|
1721
|
34
|
|
|
|
|
81
|
A private path to the Catalyst action you want to create a URI for. |
|
37
|
|
|
|
|
72
|
|
1722
|
37
|
|
|
|
|
160
|
|
1723
|
|
|
|
|
|
|
This is a shortcut for calling C<< $c->dispatcher->get_action_by_path($path) |
1724
|
37
|
|
|
|
|
155
|
>> and passing the resulting C<$action> and the remaining arguments to C<< |
1725
|
37
|
|
|
|
|
77
|
$c->uri_for >>. |
1726
|
|
|
|
|
|
|
|
1727
|
37
|
100
|
|
|
|
90
|
You can also pass in a Catalyst::Action object, in which case it is passed to |
1728
|
|
|
|
|
|
|
C<< $c->uri_for >>. |
1729
|
37
|
100
|
|
|
|
98
|
|
|
38
|
|
|
|
|
208
|
|
1730
|
|
|
|
|
|
|
Note that although the path looks like a URI that dispatches to the wanted action, it is not a URI, but an internal path to that action. |
1731
|
38
|
|
|
|
|
231
|
|
1732
|
38
|
|
|
|
|
91
|
For example, if the action looks like: |
1733
|
|
|
|
|
|
|
|
1734
|
38
|
|
|
|
|
183
|
package MyApp::Controller::Users; |
1735
|
|
|
|
|
|
|
|
1736
|
|
|
|
|
|
|
sub lst : Path('the-list') {} |
1737
|
|
|
|
|
|
|
|
1738
|
|
|
|
|
|
|
You can use: |
1739
|
113
|
|
|
|
|
430
|
|
1740
|
113
|
|
|
|
|
826
|
$c->uri_for_action('/users/lst') |
1741
|
113
|
|
|
|
|
300
|
|
1742
|
113
|
|
|
|
|
560
|
and it will create the URI /users/the-list. |
1743
|
|
|
|
|
|
|
|
1744
|
113
|
100
|
|
|
|
297
|
=item \@captures_and_args? |
1745
|
7
|
100
|
|
|
|
22
|
|
1746
|
1
|
|
|
|
|
4
|
Optional array reference of Captures (i.e. C<CaptureArgs> or C<< $c->req->captures >>) |
1747
|
1
|
|
|
|
|
4
|
and arguments to the request. Usually used with L<Catalyst::DispatchType::Chained> |
1748
|
1
|
|
|
|
|
4
|
to interpolate all the parameters in the URI. |
1749
|
|
|
|
|
|
|
|
1750
|
7
|
|
|
|
|
13
|
=item @args? |
1751
|
|
|
|
|
|
|
|
1752
|
|
|
|
|
|
|
Optional list of extra arguments - can be supplied in the |
1753
|
113
|
|
|
|
|
403
|
C<< \@captures_and_args? >> array ref, or here - whichever is easier for your |
1754
|
113
|
|
|
|
|
1810
|
code. |
1755
|
|
|
|
|
|
|
|
1756
|
|
|
|
|
|
|
Your action can have zero, a fixed or a variable number of args (e.g. |
1757
|
|
|
|
|
|
|
C<< Args(1) >> for a fixed number or C<< Args() >> for a variable number).. |
1758
|
|
|
|
|
|
|
|
1759
|
|
|
|
|
|
|
=item \%query_values? |
1760
|
|
|
|
|
|
|
|
1761
|
|
|
|
|
|
|
Optional array reference of query parameters to append. E.g. |
1762
|
|
|
|
|
|
|
|
1763
|
|
|
|
|
|
|
{ foo => 'bar' } |
1764
|
|
|
|
|
|
|
|
1765
|
|
|
|
|
|
|
will generate |
1766
|
|
|
|
|
|
|
|
1767
|
|
|
|
|
|
|
/rest/of/your/uri?foo=bar |
1768
|
|
|
|
|
|
|
|
1769
|
|
|
|
|
|
|
=back |
1770
|
|
|
|
|
|
|
|
1771
|
|
|
|
|
|
|
=cut |
1772
|
|
|
|
|
|
|
|
1773
|
|
|
|
|
|
|
my ( $c, $path, @args ) = @_; |
1774
|
|
|
|
|
|
|
my $action = blessed($path) |
1775
|
|
|
|
|
|
|
? $path |
1776
|
|
|
|
|
|
|
: $c->dispatcher->get_action_by_path($path); |
1777
|
|
|
|
|
|
|
unless (defined $action) { |
1778
|
|
|
|
|
|
|
croak "Can't find action for path '$path'"; |
1779
|
|
|
|
|
|
|
} |
1780
|
|
|
|
|
|
|
return $c->uri_for( $action, @args ); |
1781
|
|
|
|
|
|
|
} |
1782
|
|
|
|
|
|
|
|
1783
|
|
|
|
|
|
|
=head2 $c->welcome_message |
1784
|
|
|
|
|
|
|
|
1785
|
|
|
|
|
|
|
Returns the Catalyst welcome HTML page. |
1786
|
|
|
|
|
|
|
|
1787
|
|
|
|
|
|
|
=cut |
1788
|
|
|
|
|
|
|
|
1789
|
|
|
|
|
|
|
my $c = shift; |
1790
|
|
|
|
|
|
|
my $name = $c->config->{name}; |
1791
|
|
|
|
|
|
|
my $logo = $c->uri_for('/static/images/catalyst_logo.png'); |
1792
|
|
|
|
|
|
|
my $prefix = Catalyst::Utils::appprefix( ref $c ); |
1793
|
|
|
|
|
|
|
$c->response->content_type('text/html; charset=utf-8'); |
1794
|
|
|
|
|
|
|
return <<"EOF"; |
1795
|
|
|
|
|
|
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" |
1796
|
|
|
|
|
|
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
1797
|
|
|
|
|
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> |
1798
|
|
|
|
|
|
|
<head> |
1799
|
|
|
|
|
|
|
<meta http-equiv="Content-Language" content="en" /> |
1800
|
|
|
|
|
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
1801
|
|
|
|
|
|
|
<title>$name on Catalyst $VERSION</title> |
1802
|
|
|
|
|
|
|
<style type="text/css"> |
1803
|
|
|
|
|
|
|
body { |
1804
|
|
|
|
|
|
|
color: #000; |
1805
|
|
|
|
|
|
|
background-color: #eee; |
1806
|
|
|
|
|
|
|
} |
1807
|
|
|
|
|
|
|
div#content { |
1808
|
|
|
|
|
|
|
width: 640px; |
1809
|
|
|
|
|
|
|
margin-left: auto; |
1810
|
|
|
|
|
|
|
margin-right: auto; |
1811
|
|
|
|
|
|
|
margin-top: 10px; |
1812
|
|
|
|
|
|
|
margin-bottom: 10px; |
1813
|
|
|
|
|
|
|
text-align: left; |
1814
|
|
|
|
|
|
|
background-color: #ccc; |
1815
|
|
|
|
|
|
|
border: 1px solid #aaa; |
1816
|
|
|
|
|
|
|
} |
1817
|
|
|
|
|
|
|
p, h1, h2 { |
1818
|
31
|
|
|
31
|
1
|
4721
|
margin-left: 20px; |
1819
|
31
|
100
|
|
|
|
156
|
margin-right: 20px; |
1820
|
|
|
|
|
|
|
font-family: verdana, tahoma, sans-serif; |
1821
|
|
|
|
|
|
|
} |
1822
|
31
|
100
|
|
|
|
79
|
a { |
1823
|
1
|
|
|
|
|
218
|
font-family: verdana, tahoma, sans-serif; |
1824
|
|
|
|
|
|
|
} |
1825
|
30
|
|
|
|
|
104
|
:link, :visited { |
1826
|
|
|
|
|
|
|
text-decoration: none; |
1827
|
|
|
|
|
|
|
color: #b00; |
1828
|
|
|
|
|
|
|
border-bottom: 1px dotted #bbb; |
1829
|
|
|
|
|
|
|
} |
1830
|
|
|
|
|
|
|
:link:hover, :visited:hover { |
1831
|
|
|
|
|
|
|
color: #555; |
1832
|
|
|
|
|
|
|
} |
1833
|
|
|
|
|
|
|
div#topbar { |
1834
|
|
|
|
|
|
|
margin: 0px; |
1835
|
0
|
|
|
0
|
1
|
0
|
} |
1836
|
0
|
|
|
|
|
0
|
pre { |
1837
|
0
|
|
|
|
|
0
|
margin: 10px; |
1838
|
0
|
|
|
|
|
0
|
padding: 8px; |
1839
|
0
|
|
|
|
|
0
|
} |
1840
|
0
|
|
|
|
|
0
|
div#answers { |
1841
|
|
|
|
|
|
|
padding: 8px; |
1842
|
|
|
|
|
|
|
margin: 10px; |
1843
|
|
|
|
|
|
|
background-color: #fff; |
1844
|
|
|
|
|
|
|
border: 1px solid #aaa; |
1845
|
|
|
|
|
|
|
} |
1846
|
|
|
|
|
|
|
h1 { |
1847
|
|
|
|
|
|
|
font-size: 0.9em; |
1848
|
|
|
|
|
|
|
font-weight: normal; |
1849
|
|
|
|
|
|
|
text-align: center; |
1850
|
|
|
|
|
|
|
} |
1851
|
|
|
|
|
|
|
h2 { |
1852
|
|
|
|
|
|
|
font-size: 1.0em; |
1853
|
|
|
|
|
|
|
} |
1854
|
|
|
|
|
|
|
p { |
1855
|
|
|
|
|
|
|
font-size: 0.9em; |
1856
|
|
|
|
|
|
|
} |
1857
|
|
|
|
|
|
|
p img { |
1858
|
|
|
|
|
|
|
float: right; |
1859
|
|
|
|
|
|
|
margin-left: 10px; |
1860
|
|
|
|
|
|
|
} |
1861
|
|
|
|
|
|
|
span#appname { |
1862
|
|
|
|
|
|
|
font-weight: bold; |
1863
|
|
|
|
|
|
|
font-size: 1.6em; |
1864
|
|
|
|
|
|
|
} |
1865
|
|
|
|
|
|
|
</style> |
1866
|
|
|
|
|
|
|
</head> |
1867
|
|
|
|
|
|
|
<body> |
1868
|
|
|
|
|
|
|
<div id="content"> |
1869
|
|
|
|
|
|
|
<div id="topbar"> |
1870
|
|
|
|
|
|
|
<h1><span id="appname">$name</span> on <a href="http://catalyst.perl.org">Catalyst</a> |
1871
|
|
|
|
|
|
|
$VERSION</h1> |
1872
|
|
|
|
|
|
|
</div> |
1873
|
|
|
|
|
|
|
<div id="answers"> |
1874
|
|
|
|
|
|
|
<p> |
1875
|
|
|
|
|
|
|
<img src="$logo" alt="Catalyst Logo" /> |
1876
|
|
|
|
|
|
|
</p> |
1877
|
|
|
|
|
|
|
<p>Welcome to the world of Catalyst. |
1878
|
|
|
|
|
|
|
This <a href="http://en.wikipedia.org/wiki/MVC">MVC</a> |
1879
|
|
|
|
|
|
|
framework will make web development something you had |
1880
|
|
|
|
|
|
|
never expected it to be: Fun, rewarding, and quick.</p> |
1881
|
|
|
|
|
|
|
<h2>What to do now?</h2> |
1882
|
|
|
|
|
|
|
<p>That really depends on what <b>you</b> want to do. |
1883
|
|
|
|
|
|
|
We do, however, provide you with a few starting points.</p> |
1884
|
|
|
|
|
|
|
<p>If you want to jump right into web development with Catalyst |
1885
|
|
|
|
|
|
|
you might want to start with a tutorial.</p> |
1886
|
|
|
|
|
|
|
<pre>perldoc <a href="https://metacpan.org/module/Catalyst::Manual::Tutorial">Catalyst::Manual::Tutorial</a></code> |
1887
|
|
|
|
|
|
|
</pre> |
1888
|
|
|
|
|
|
|
<p>Afterwards you can go on to check out a more complete look at our features.</p> |
1889
|
|
|
|
|
|
|
<pre> |
1890
|
|
|
|
|
|
|
<code>perldoc <a href="https://metacpan.org/module/Catalyst::Manual::Intro">Catalyst::Manual::Intro</a> |
1891
|
|
|
|
|
|
|
<!-- Something else should go here, but the Catalyst::Manual link seems unhelpful --> |
1892
|
|
|
|
|
|
|
</code></pre> |
1893
|
|
|
|
|
|
|
<h2>What to do next?</h2> |
1894
|
|
|
|
|
|
|
<p>Next it's time to write an actual application. Use the |
1895
|
|
|
|
|
|
|
helper scripts to generate <a href="https://metacpan.org/search?q=Catalyst%3A%3AController">controllers</a>, |
1896
|
|
|
|
|
|
|
<a href="https://metacpan.org/search?q=Catalyst%3A%3AModel">models</a>, and |
1897
|
|
|
|
|
|
|
<a href="https://metacpan.org/search?q=Catalyst%3A%3AView">views</a>; |
1898
|
|
|
|
|
|
|
they can save you a lot of work.</p> |
1899
|
|
|
|
|
|
|
<pre><code>script/${prefix}_create.pl --help</code></pre> |
1900
|
|
|
|
|
|
|
<p>Also, be sure to check out the vast and growing |
1901
|
|
|
|
|
|
|
collection of <a href="http://search.cpan.org/search?query=Catalyst">plugins for Catalyst on CPAN</a>; |
1902
|
|
|
|
|
|
|
you are likely to find what you need there. |
1903
|
|
|
|
|
|
|
</p> |
1904
|
|
|
|
|
|
|
|
1905
|
|
|
|
|
|
|
<h2>Need help?</h2> |
1906
|
|
|
|
|
|
|
<p>Catalyst has a very active community. Here are the main places to |
1907
|
|
|
|
|
|
|
get in touch with us.</p> |
1908
|
|
|
|
|
|
|
<ul> |
1909
|
|
|
|
|
|
|
<li> |
1910
|
|
|
|
|
|
|
<a href="http://dev.catalyst.perl.org">Wiki</a> |
1911
|
|
|
|
|
|
|
</li> |
1912
|
|
|
|
|
|
|
<li> |
1913
|
|
|
|
|
|
|
<a href="http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst">Mailing-List</a> |
1914
|
|
|
|
|
|
|
</li> |
1915
|
|
|
|
|
|
|
<li> |
1916
|
|
|
|
|
|
|
<a href="irc://irc.perl.org/catalyst">IRC channel #catalyst on irc.perl.org</a> |
1917
|
|
|
|
|
|
|
</li> |
1918
|
|
|
|
|
|
|
</ul> |
1919
|
|
|
|
|
|
|
<h2>In conclusion</h2> |
1920
|
|
|
|
|
|
|
<p>The Catalyst team hopes you will enjoy using Catalyst as much |
1921
|
|
|
|
|
|
|
as we enjoyed making it. Please contact us if you have ideas |
1922
|
|
|
|
|
|
|
for improvement or other feedback.</p> |
1923
|
|
|
|
|
|
|
</div> |
1924
|
|
|
|
|
|
|
</div> |
1925
|
|
|
|
|
|
|
</body> |
1926
|
|
|
|
|
|
|
</html> |
1927
|
|
|
|
|
|
|
EOF |
1928
|
|
|
|
|
|
|
} |
1929
|
|
|
|
|
|
|
|
1930
|
|
|
|
|
|
|
=head2 run_options |
1931
|
|
|
|
|
|
|
|
1932
|
|
|
|
|
|
|
Contains a hash of options passed from the application script, including |
1933
|
|
|
|
|
|
|
the original ARGV the script received, the processed values from that |
1934
|
|
|
|
|
|
|
ARGV and any extra arguments to the script which were not processed. |
1935
|
|
|
|
|
|
|
|
1936
|
|
|
|
|
|
|
This can be used to add custom options to your application's scripts |
1937
|
|
|
|
|
|
|
and setup your application differently depending on the values of these |
1938
|
|
|
|
|
|
|
options. |
1939
|
|
|
|
|
|
|
|
1940
|
|
|
|
|
|
|
=head1 INTERNAL METHODS |
1941
|
|
|
|
|
|
|
|
1942
|
|
|
|
|
|
|
These methods are not meant to be used by end users. |
1943
|
|
|
|
|
|
|
|
1944
|
|
|
|
|
|
|
=head2 $c->components |
1945
|
|
|
|
|
|
|
|
1946
|
|
|
|
|
|
|
Returns a hash of components. |
1947
|
|
|
|
|
|
|
|
1948
|
|
|
|
|
|
|
=head2 $c->context_class |
1949
|
|
|
|
|
|
|
|
1950
|
|
|
|
|
|
|
Returns or sets the context class. |
1951
|
|
|
|
|
|
|
|
1952
|
|
|
|
|
|
|
=head2 $c->counter |
1953
|
|
|
|
|
|
|
|
1954
|
|
|
|
|
|
|
Returns a hashref containing coderefs and execution counts (needed for |
1955
|
|
|
|
|
|
|
deep recursion detection). |
1956
|
|
|
|
|
|
|
|
1957
|
|
|
|
|
|
|
=head2 $c->depth |
1958
|
|
|
|
|
|
|
|
1959
|
|
|
|
|
|
|
Returns the number of actions on the current internal execution stack. |
1960
|
|
|
|
|
|
|
|
1961
|
|
|
|
|
|
|
=head2 $c->dispatch |
1962
|
|
|
|
|
|
|
|
1963
|
|
|
|
|
|
|
Dispatches a request to actions. |
1964
|
|
|
|
|
|
|
|
1965
|
|
|
|
|
|
|
=cut |
1966
|
|
|
|
|
|
|
|
1967
|
|
|
|
|
|
|
|
1968
|
|
|
|
|
|
|
=head2 $c->dispatcher_class |
1969
|
|
|
|
|
|
|
|
1970
|
|
|
|
|
|
|
Returns or sets the dispatcher class. |
1971
|
|
|
|
|
|
|
|
1972
|
|
|
|
|
|
|
=head2 $c->dump_these |
1973
|
|
|
|
|
|
|
|
1974
|
|
|
|
|
|
|
Returns a list of 2-element array references (name, structure) pairs |
1975
|
|
|
|
|
|
|
that will be dumped on the error page in debug mode. |
1976
|
|
|
|
|
|
|
|
1977
|
|
|
|
|
|
|
=cut |
1978
|
|
|
|
|
|
|
|
1979
|
|
|
|
|
|
|
my $c = shift; |
1980
|
|
|
|
|
|
|
[ Request => $c->req ], |
1981
|
|
|
|
|
|
|
[ Response => $c->res ], |
1982
|
|
|
|
|
|
|
[ Stash => $c->stash ], |
1983
|
|
|
|
|
|
|
[ Config => $c->config ]; |
1984
|
|
|
|
|
|
|
} |
1985
|
|
|
|
|
|
|
|
1986
|
|
|
|
|
|
|
=head2 $c->engine_class |
1987
|
|
|
|
|
|
|
|
1988
|
|
|
|
|
|
|
Returns or sets the engine class. |
1989
|
|
|
|
|
|
|
|
1990
|
|
|
|
|
|
|
=head2 $c->execute( $class, $coderef ) |
1991
|
|
|
|
|
|
|
|
1992
|
|
|
|
|
|
|
Execute a coderef in given class and catch exceptions. Errors are available |
1993
|
|
|
|
|
|
|
via $c->error. |
1994
|
|
|
|
|
|
|
|
1995
|
|
|
|
|
|
|
=cut |
1996
|
|
|
|
|
|
|
|
1997
|
|
|
|
|
|
|
my ( $c, $class, $code ) = @_; |
1998
|
|
|
|
|
|
|
$class = $c->component($class) || $class; |
1999
|
|
|
|
|
|
|
#$c->state(0); |
2000
|
|
|
|
|
|
|
|
2001
|
|
|
|
|
|
|
if ( $c->depth >= $RECURSION ) { |
2002
|
|
|
|
|
|
|
my $action = $code->reverse(); |
2003
|
|
|
|
|
|
|
$action = "/$action" unless $action =~ /->/; |
2004
|
|
|
|
|
|
|
my $error = qq/Deep recursion detected calling "${action}"/; |
2005
|
|
|
|
|
|
|
$c->log->error($error); |
2006
|
|
|
|
|
|
|
$c->error($error); |
2007
|
|
|
|
|
|
|
$c->state(0); |
2008
|
|
|
|
|
|
|
return $c->state; |
2009
|
|
|
|
|
|
|
} |
2010
|
|
|
|
|
|
|
|
2011
|
|
|
|
|
|
|
my $stats_info = $c->_stats_start_execute( $code ) if $c->use_stats; |
2012
|
|
|
|
|
|
|
|
2013
|
920
|
|
|
920
|
1
|
3717
|
push( @{ $c->stack }, $code ); |
|
920
|
|
|
|
|
3517
|
|
2014
|
|
|
|
|
|
|
|
2015
|
|
|
|
|
|
|
no warnings 'recursion'; |
2016
|
|
|
|
|
|
|
# N.B. This used to be combined, but I have seen $c get clobbered if so, and |
2017
|
|
|
|
|
|
|
# I have no idea how, ergo $ret (which appears to fix the issue) |
2018
|
|
|
|
|
|
|
eval { my $ret = $code->execute( $class, $c, @{ $c->req->args } ) || 0; $c->state( $ret ) }; |
2019
|
|
|
|
|
|
|
|
2020
|
|
|
|
|
|
|
$c->_stats_finish_execute( $stats_info ) if $c->use_stats and $stats_info; |
2021
|
|
|
|
|
|
|
|
2022
|
|
|
|
|
|
|
my $last = pop( @{ $c->stack } ); |
2023
|
|
|
|
|
|
|
|
2024
|
|
|
|
|
|
|
if ( my $error = $@ ) { |
2025
|
|
|
|
|
|
|
#rethow if this can be handled by middleware |
2026
|
|
|
|
|
|
|
if ( $c->_handle_http_exception($error) ) { |
2027
|
36
|
|
|
36
|
1
|
65
|
foreach my $err (@{$c->error}) { |
2028
|
36
|
|
|
|
|
117
|
$c->log->error($err); |
2029
|
|
|
|
|
|
|
} |
2030
|
|
|
|
|
|
|
$c->clear_errors; |
2031
|
|
|
|
|
|
|
$c->log->_flush if $c->log->can('_flush'); |
2032
|
|
|
|
|
|
|
|
2033
|
|
|
|
|
|
|
$error->can('rethrow') ? $error->rethrow : croak $error; |
2034
|
|
|
|
|
|
|
} |
2035
|
|
|
|
|
|
|
if ( blessed($error) and $error->isa('Catalyst::Exception::Detach') ) { |
2036
|
|
|
|
|
|
|
$error->rethrow if $c->depth > 1; |
2037
|
|
|
|
|
|
|
} |
2038
|
|
|
|
|
|
|
elsif ( blessed($error) and $error->isa('Catalyst::Exception::Go') ) { |
2039
|
|
|
|
|
|
|
$error->rethrow if $c->depth > 0; |
2040
|
|
|
|
|
|
|
} |
2041
|
|
|
|
|
|
|
else { |
2042
|
|
|
|
|
|
|
unless ( ref $error ) { |
2043
|
|
|
|
|
|
|
no warnings 'uninitialized'; |
2044
|
|
|
|
|
|
|
chomp $error; |
2045
|
|
|
|
|
|
|
my $class = $last->class; |
2046
|
9126
|
|
|
9126
|
1
|
262699
|
my $name = $last->name; |
2047
|
9126
|
|
66
|
|
|
22215
|
$error = qq/Caught exception in $class->$name "$error"/; |
2048
|
|
|
|
|
|
|
} |
2049
|
|
|
|
|
|
|
$c->error($error); |
2050
|
9126
|
100
|
|
|
|
22138
|
} |
2051
|
1
|
|
|
|
|
31
|
#$c->state(0); |
2052
|
1
|
50
|
|
|
|
10
|
} |
2053
|
1
|
|
|
|
|
5
|
return $c->state; |
2054
|
1
|
|
|
|
|
6
|
} |
2055
|
1
|
|
|
|
|
10
|
|
2056
|
1
|
|
|
|
|
30
|
my ( $c, $code ) = @_; |
2057
|
1
|
|
|
|
|
23
|
my $appclass = ref($c) || $c; |
2058
|
|
|
|
|
|
|
return if ( ( $code->name =~ /^_.*/ ) |
2059
|
|
|
|
|
|
|
&& ( !$appclass->config->{show_internal_actions} ) ); |
2060
|
9125
|
100
|
|
|
|
23095
|
|
2061
|
|
|
|
|
|
|
my $action_name = $code->reverse(); |
2062
|
9125
|
|
|
|
|
13239
|
$c->counter->{$action_name}++; |
|
9125
|
|
|
|
|
198486
|
|
2063
|
|
|
|
|
|
|
|
2064
|
164
|
|
|
164
|
|
1553
|
my $action = $action_name; |
|
164
|
|
|
|
|
437
|
|
|
164
|
|
|
|
|
42833
|
|
2065
|
|
|
|
|
|
|
$action = "/$action" unless $action =~ /->/; |
2066
|
|
|
|
|
|
|
|
2067
|
9125
|
|
100
|
|
|
15366
|
# determine if the call was the result of a forward |
|
9125
|
|
|
|
|
13582
|
|
|
8999
|
|
|
|
|
284543
|
|
2068
|
|
|
|
|
|
|
# this is done by walking up the call stack and looking for a calling |
2069
|
9122
|
100
|
100
|
|
|
20233
|
# sub of Catalyst::forward before the eval |
2070
|
|
|
|
|
|
|
my $callsub = q{}; |
2071
|
9122
|
|
|
|
|
13687
|
for my $index ( 2 .. 11 ) { |
|
9122
|
|
|
|
|
198267
|
|
2072
|
|
|
|
|
|
|
last |
2073
|
9122
|
100
|
|
|
|
23528
|
if ( ( caller($index) )[0] eq 'Catalyst' |
2074
|
|
|
|
|
|
|
&& ( caller($index) )[3] eq '(eval)' ); |
2075
|
123
|
100
|
|
|
|
484
|
|
2076
|
9
|
|
|
|
|
13
|
if ( ( caller($index) )[3] =~ /forward$/ ) { |
|
9
|
|
|
|
|
23
|
|
2077
|
0
|
|
|
|
|
0
|
$callsub = ( caller($index) )[3]; |
2078
|
|
|
|
|
|
|
$action = "-> $action"; |
2079
|
9
|
|
|
|
|
27
|
last; |
2080
|
9
|
50
|
|
|
|
29
|
} |
2081
|
|
|
|
|
|
|
} |
2082
|
9
|
50
|
|
|
|
379
|
|
2083
|
|
|
|
|
|
|
my $uid = $action_name . $c->counter->{$action_name}; |
2084
|
114
|
100
|
100
|
|
|
1182
|
|
|
|
100
|
100
|
|
|
|
|
2085
|
27
|
100
|
|
|
|
79
|
# is this a root-level call or a forwarded call? |
2086
|
|
|
|
|
|
|
if ( $callsub =~ /forward$/ ) { |
2087
|
|
|
|
|
|
|
my $parent = $c->stack->[-1]; |
2088
|
66
|
100
|
|
|
|
160
|
|
2089
|
|
|
|
|
|
|
# forward, locate the caller |
2090
|
|
|
|
|
|
|
if ( defined $parent && exists $c->counter->{"$parent"} ) { |
2091
|
21
|
100
|
|
|
|
101
|
$c->stats->profile( |
2092
|
164
|
|
|
164
|
|
1418
|
begin => $action, |
|
164
|
|
|
|
|
563
|
|
|
164
|
|
|
|
|
1557481
|
|
2093
|
13
|
|
|
|
|
46
|
parent => "$parent" . $c->counter->{"$parent"}, |
2094
|
13
|
|
|
|
|
446
|
uid => $uid, |
2095
|
13
|
|
|
|
|
359
|
); |
2096
|
13
|
|
|
|
|
82
|
} |
2097
|
|
|
|
|
|
|
else { |
2098
|
21
|
|
|
|
|
88
|
|
2099
|
|
|
|
|
|
|
# forward with no caller may come from a plugin |
2100
|
|
|
|
|
|
|
$c->stats->profile( |
2101
|
|
|
|
|
|
|
begin => $action, |
2102
|
9045
|
|
|
|
|
196178
|
uid => $uid, |
2103
|
|
|
|
|
|
|
); |
2104
|
|
|
|
|
|
|
} |
2105
|
|
|
|
|
|
|
} |
2106
|
111
|
|
|
111
|
|
212
|
else { |
2107
|
111
|
|
33
|
|
|
274
|
|
2108
|
|
|
|
|
|
|
# root-level call |
2109
|
111
|
100
|
100
|
|
|
2910
|
$c->stats->profile( |
2110
|
|
|
|
|
|
|
begin => $action, |
2111
|
29
|
|
|
|
|
829
|
uid => $uid, |
2112
|
29
|
|
|
|
|
732
|
); |
2113
|
|
|
|
|
|
|
} |
2114
|
29
|
|
|
|
|
65
|
return $action; |
2115
|
29
|
50
|
|
|
|
131
|
|
2116
|
|
|
|
|
|
|
} |
2117
|
|
|
|
|
|
|
|
2118
|
|
|
|
|
|
|
my ( $c, $info ) = @_; |
2119
|
|
|
|
|
|
|
$c->stats->profile( end => $info ); |
2120
|
29
|
|
|
|
|
69
|
} |
2121
|
29
|
|
|
|
|
95
|
|
2122
|
|
|
|
|
|
|
=head2 $c->finalize |
2123
|
111
|
100
|
100
|
|
|
743
|
|
2124
|
|
|
|
|
|
|
Finalizes the request. |
2125
|
|
|
|
|
|
|
|
2126
|
87
|
100
|
|
|
|
411
|
=cut |
2127
|
5
|
|
|
|
|
22
|
|
2128
|
5
|
|
|
|
|
13
|
my $c = shift; |
2129
|
5
|
|
|
|
|
10
|
|
2130
|
|
|
|
|
|
|
for my $error ( @{ $c->error } ) { |
2131
|
|
|
|
|
|
|
$c->log->error($error); |
2132
|
|
|
|
|
|
|
} |
2133
|
29
|
|
|
|
|
758
|
|
2134
|
|
|
|
|
|
|
# Support skipping finalize for psgix.io style 'jailbreak'. Used to support |
2135
|
|
|
|
|
|
|
# stuff like cometd and websockets |
2136
|
29
|
100
|
|
|
|
107
|
|
2137
|
5
|
|
|
|
|
114
|
if($c->request->_has_io_fh) { |
2138
|
|
|
|
|
|
|
$c->log_response; |
2139
|
|
|
|
|
|
|
return; |
2140
|
5
|
100
|
66
|
|
|
100
|
} |
2141
|
|
|
|
|
|
|
|
2142
|
|
|
|
|
|
|
# Allow engine to handle finalize flow (for POE) |
2143
|
4
|
|
|
|
|
94
|
my $engine = $c->engine; |
2144
|
|
|
|
|
|
|
if ( my $code = $engine->can('finalize') ) { |
2145
|
|
|
|
|
|
|
$engine->$code($c); |
2146
|
|
|
|
|
|
|
} |
2147
|
|
|
|
|
|
|
else { |
2148
|
|
|
|
|
|
|
|
2149
|
|
|
|
|
|
|
$c->finalize_uploads; |
2150
|
1
|
|
|
|
|
24
|
|
2151
|
|
|
|
|
|
|
# Error |
2152
|
|
|
|
|
|
|
if ( $#{ $c->error } >= 0 ) { |
2153
|
|
|
|
|
|
|
$c->finalize_error; |
2154
|
|
|
|
|
|
|
} |
2155
|
|
|
|
|
|
|
|
2156
|
|
|
|
|
|
|
$c->finalize_encoding; |
2157
|
|
|
|
|
|
|
$c->finalize_headers unless $c->response->finalized_headers; |
2158
|
|
|
|
|
|
|
$c->finalize_body; |
2159
|
24
|
|
|
|
|
553
|
} |
2160
|
|
|
|
|
|
|
|
2161
|
|
|
|
|
|
|
$c->log_response; |
2162
|
|
|
|
|
|
|
|
2163
|
|
|
|
|
|
|
$c->log_stats if $c->use_stats; |
2164
|
29
|
|
|
|
|
190
|
|
2165
|
|
|
|
|
|
|
return $c->response->status; |
2166
|
|
|
|
|
|
|
} |
2167
|
|
|
|
|
|
|
|
2168
|
|
|
|
|
|
|
=head2 $c->log_stats |
2169
|
29
|
|
|
29
|
|
71
|
|
2170
|
29
|
|
|
|
|
713
|
Logs statistics. |
2171
|
|
|
|
|
|
|
|
2172
|
|
|
|
|
|
|
=cut |
2173
|
|
|
|
|
|
|
|
2174
|
|
|
|
|
|
|
my $c = shift; |
2175
|
|
|
|
|
|
|
|
2176
|
|
|
|
|
|
|
my $elapsed = $c->stats->elapsed; |
2177
|
|
|
|
|
|
|
my $av = $elapsed == 0 ? '??' : sprintf '%.3f', 1 / $elapsed; |
2178
|
|
|
|
|
|
|
$c->log->info( |
2179
|
|
|
|
|
|
|
"Request took ${elapsed}s ($av/s)\n" . $c->stats->report . "\n" ); |
2180
|
920
|
|
|
920
|
1
|
2353
|
} |
2181
|
|
|
|
|
|
|
|
2182
|
920
|
|
|
|
|
1709
|
|
|
920
|
|
|
|
|
2741
|
|
2183
|
37
|
|
|
|
|
188
|
=head2 $c->finalize_body |
2184
|
|
|
|
|
|
|
|
2185
|
|
|
|
|
|
|
Finalizes body. |
2186
|
|
|
|
|
|
|
|
2187
|
|
|
|
|
|
|
=cut |
2188
|
|
|
|
|
|
|
|
2189
|
920
|
50
|
|
|
|
24018
|
|
2190
|
0
|
|
|
|
|
0
|
=head2 $c->finalize_cookies |
2191
|
0
|
|
|
|
|
0
|
|
2192
|
|
|
|
|
|
|
Finalizes cookies. |
2193
|
|
|
|
|
|
|
|
2194
|
|
|
|
|
|
|
=cut |
2195
|
920
|
|
|
|
|
3991
|
|
2196
|
920
|
50
|
|
|
|
5940
|
|
2197
|
0
|
|
|
|
|
0
|
=head2 $c->finalize_error |
2198
|
|
|
|
|
|
|
|
2199
|
|
|
|
|
|
|
Finalizes error. If there is only one error in L</error> and it is an object that |
2200
|
|
|
|
|
|
|
does C<as_psgi> or C<code> we rethrow the error and presume it caught by middleware |
2201
|
920
|
|
|
|
|
4299
|
up the ladder. Otherwise we return the debugging error page (in debug mode) or we |
2202
|
|
|
|
|
|
|
return the default error page (production mode). |
2203
|
|
|
|
|
|
|
|
2204
|
920
|
100
|
|
|
|
1941
|
=cut |
|
920
|
|
|
|
|
3232
|
|
2205
|
34
|
|
|
|
|
209
|
|
2206
|
|
|
|
|
|
|
my $c = shift; |
2207
|
|
|
|
|
|
|
if($#{$c->error} > 0) { |
2208
|
920
|
|
|
|
|
5029
|
$c->engine->finalize_error( $c, @_ ); |
2209
|
920
|
100
|
|
|
|
32646
|
} else { |
2210
|
920
|
|
|
|
|
4460
|
my ($error) = @{$c->error}; |
2211
|
|
|
|
|
|
|
if ( $c->_handle_http_exception($error) ) { |
2212
|
|
|
|
|
|
|
# In the case where the error 'knows what it wants', becauses its PSGI |
2213
|
920
|
|
|
|
|
5254
|
# aware, just rethow and let middleware catch it |
2214
|
|
|
|
|
|
|
$error->can('rethrow') ? $error->rethrow : croak $error; |
2215
|
920
|
100
|
|
|
|
3028
|
} else { |
2216
|
|
|
|
|
|
|
$c->engine->finalize_error( $c, @_ ) |
2217
|
920
|
|
|
|
|
24332
|
} |
2218
|
|
|
|
|
|
|
} |
2219
|
|
|
|
|
|
|
} |
2220
|
|
|
|
|
|
|
|
2221
|
|
|
|
|
|
|
=head2 $c->finalize_headers |
2222
|
|
|
|
|
|
|
|
2223
|
|
|
|
|
|
|
Finalizes headers. |
2224
|
|
|
|
|
|
|
|
2225
|
|
|
|
|
|
|
=cut |
2226
|
|
|
|
|
|
|
|
2227
|
15
|
|
|
15
|
1
|
35
|
my $c = shift; |
2228
|
|
|
|
|
|
|
|
2229
|
15
|
|
|
|
|
404
|
my $response = $c->response; #accessor calls can add up? |
2230
|
15
|
50
|
|
|
|
588
|
|
2231
|
15
|
|
|
|
|
66
|
# Check if we already finalized headers |
2232
|
|
|
|
|
|
|
return if $response->finalized_headers; |
2233
|
|
|
|
|
|
|
|
2234
|
|
|
|
|
|
|
# Handle redirects |
2235
|
|
|
|
|
|
|
if ( my $location = $response->redirect ) { |
2236
|
|
|
|
|
|
|
$c->log->debug(qq/Redirecting to "$location"/) if $c->debug; |
2237
|
|
|
|
|
|
|
$response->header( Location => $location ); |
2238
|
|
|
|
|
|
|
} |
2239
|
|
|
|
|
|
|
|
2240
|
|
|
|
|
|
|
# Remove incorrectly added body and content related meta data when returning |
2241
|
|
|
|
|
|
|
# an information response, or a response the is required to not include a body |
2242
|
920
|
|
|
920
|
1
|
2046
|
|
|
920
|
|
|
|
|
2902
|
|
2243
|
|
|
|
|
|
|
$c->finalize_cookies; |
2244
|
|
|
|
|
|
|
|
2245
|
|
|
|
|
|
|
# This currently is a NOOP but I don't want to remove it since I guess people |
2246
|
|
|
|
|
|
|
# might have Response subclasses that use it for something... (JNAP) |
2247
|
|
|
|
|
|
|
$c->response->finalize_headers(); |
2248
|
|
|
|
|
|
|
|
2249
|
|
|
|
|
|
|
# Done |
2250
|
920
|
|
|
920
|
1
|
1804
|
$response->finalized_headers(1); |
|
920
|
|
|
|
|
3322
|
|
2251
|
|
|
|
|
|
|
} |
2252
|
|
|
|
|
|
|
|
2253
|
|
|
|
|
|
|
=head2 $c->finalize_encoding |
2254
|
|
|
|
|
|
|
|
2255
|
|
|
|
|
|
|
Make sure your body is encoded properly IF you set an encoding. By |
2256
|
|
|
|
|
|
|
default the encoding is UTF-8 but you can disable it by explicitly setting the |
2257
|
|
|
|
|
|
|
encoding configuration value to undef. |
2258
|
|
|
|
|
|
|
|
2259
|
|
|
|
|
|
|
We can only encode when the body is a scalar. Methods for encoding via the |
2260
|
|
|
|
|
|
|
streaming interfaces (such as C<write> and C<write_fh> on L<Catalyst::Response> |
2261
|
|
|
|
|
|
|
are available). |
2262
|
34
|
|
|
34
|
1
|
453
|
|
2263
|
34
|
100
|
|
|
|
85
|
See L</ENCODING>. |
|
34
|
|
|
|
|
105
|
|
2264
|
3
|
|
|
|
|
23
|
|
2265
|
|
|
|
|
|
|
=cut |
2266
|
31
|
|
|
|
|
69
|
|
|
31
|
|
|
|
|
108
|
|
2267
|
31
|
50
|
|
|
|
189
|
my $c = shift; |
2268
|
|
|
|
|
|
|
my $res = $c->res || return; |
2269
|
|
|
|
|
|
|
|
2270
|
0
|
0
|
|
|
|
0
|
# Warn if the set charset is different from the one you put into encoding. We need |
2271
|
|
|
|
|
|
|
# to do this early since encodable_response is false for this condition and we need |
2272
|
31
|
|
|
|
|
161
|
# to match the debug output for backcompat (there's a test for this...) -JNAP |
2273
|
|
|
|
|
|
|
if( |
2274
|
|
|
|
|
|
|
$res->content_type_charset and $c->encoding and |
2275
|
|
|
|
|
|
|
(uc($c->encoding->mime_name) ne uc($res->content_type_charset)) |
2276
|
|
|
|
|
|
|
) { |
2277
|
|
|
|
|
|
|
my $ct = lc($res->content_type_charset); |
2278
|
|
|
|
|
|
|
$c->log->debug("Catalyst encoding config is set to encode in '" . |
2279
|
|
|
|
|
|
|
$c->encoding->mime_name . |
2280
|
|
|
|
|
|
|
"', content type is '$ct', not encoding "); |
2281
|
|
|
|
|
|
|
} |
2282
|
|
|
|
|
|
|
|
2283
|
|
|
|
|
|
|
if( |
2284
|
920
|
|
|
920
|
1
|
10674
|
($res->encodable_response) and |
2285
|
|
|
|
|
|
|
(defined($res->body)) and |
2286
|
920
|
|
|
|
|
24114
|
(ref(\$res->body) eq 'SCALAR') |
2287
|
|
|
|
|
|
|
) { |
2288
|
|
|
|
|
|
|
# if you are finding yourself here and your body is already encoded correctly |
2289
|
920
|
50
|
|
|
|
25534
|
# and you want to turn this off, use $c->clear_encoding to prevent encoding |
2290
|
|
|
|
|
|
|
# at this step, or set encoding to undef in the config to do so for the whole |
2291
|
|
|
|
|
|
|
# application. See the ENCODING documentaiton for better notes. |
2292
|
920
|
100
|
|
|
|
4881
|
$c->res->body( $c->encoding->encode( $c->res->body, $c->_encode_check ) ); |
2293
|
14
|
50
|
|
|
|
63
|
|
2294
|
14
|
|
|
|
|
58
|
# Set the charset if necessary. This might be a bit bonkers since encodable response |
2295
|
|
|
|
|
|
|
# is false when the set charset is not the same as the encoding mimetype (maybe |
2296
|
|
|
|
|
|
|
# confusing action at a distance here.. |
2297
|
|
|
|
|
|
|
# Don't try to set the charset if one already exists or if headers are already finalized |
2298
|
|
|
|
|
|
|
$c->res->content_type($c->res->content_type . "; charset=" . $c->encoding->mime_name) |
2299
|
|
|
|
|
|
|
unless($c->res->content_type_charset || |
2300
|
920
|
|
|
|
|
5339
|
($c->res->_context && $c->res->finalized_headers && !$c->res->_has_response_cb)); |
2301
|
|
|
|
|
|
|
} |
2302
|
|
|
|
|
|
|
} |
2303
|
|
|
|
|
|
|
|
2304
|
920
|
|
|
|
|
22067
|
=head2 $c->finalize_output |
2305
|
|
|
|
|
|
|
|
2306
|
|
|
|
|
|
|
An alias for finalize_body. |
2307
|
920
|
|
|
|
|
25248
|
|
2308
|
|
|
|
|
|
|
=head2 $c->finalize_read |
2309
|
|
|
|
|
|
|
|
2310
|
|
|
|
|
|
|
Finalizes the input after reading is complete. |
2311
|
|
|
|
|
|
|
|
2312
|
|
|
|
|
|
|
=cut |
2313
|
|
|
|
|
|
|
|
2314
|
|
|
|
|
|
|
|
2315
|
|
|
|
|
|
|
=head2 $c->finalize_uploads |
2316
|
|
|
|
|
|
|
|
2317
|
|
|
|
|
|
|
Finalizes uploads. Cleans up any temporary files. |
2318
|
|
|
|
|
|
|
|
2319
|
|
|
|
|
|
|
=cut |
2320
|
|
|
|
|
|
|
|
2321
|
|
|
|
|
|
|
|
2322
|
|
|
|
|
|
|
=head2 $c->get_action( $action, $namespace ) |
2323
|
|
|
|
|
|
|
|
2324
|
|
|
|
|
|
|
Gets an action in a given namespace. |
2325
|
920
|
|
|
920
|
1
|
2035
|
|
2326
|
920
|
|
50
|
|
|
2634
|
=cut |
2327
|
|
|
|
|
|
|
|
2328
|
|
|
|
|
|
|
|
2329
|
|
|
|
|
|
|
=head2 $c->get_actions( $action, $namespace ) |
2330
|
|
|
|
|
|
|
|
2331
|
920
|
100
|
100
|
|
|
5926
|
Gets all actions of a given name in a namespace and all parent |
|
|
|
100
|
|
|
|
|
2332
|
|
|
|
|
|
|
namespaces. |
2333
|
|
|
|
|
|
|
|
2334
|
|
|
|
|
|
|
=cut |
2335
|
2
|
|
|
|
|
187
|
|
2336
|
2
|
|
|
|
|
192
|
|
2337
|
|
|
|
|
|
|
=head2 $app->handle_request( @arguments ) |
2338
|
|
|
|
|
|
|
|
2339
|
|
|
|
|
|
|
Called to handle each HTTP request. |
2340
|
|
|
|
|
|
|
|
2341
|
920
|
100
|
100
|
|
|
225548
|
=cut |
|
|
|
100
|
|
|
|
|
2342
|
|
|
|
|
|
|
|
2343
|
|
|
|
|
|
|
my ( $class, @arguments ) = @_; |
2344
|
|
|
|
|
|
|
|
2345
|
|
|
|
|
|
|
# Always expect worst case! |
2346
|
|
|
|
|
|
|
my $status = -1; |
2347
|
|
|
|
|
|
|
try { |
2348
|
|
|
|
|
|
|
if ($class->debug) { |
2349
|
|
|
|
|
|
|
my $secs = time - $START || 1; |
2350
|
203
|
|
|
|
|
757
|
my $av = sprintf '%.3f', $COUNT / $secs; |
2351
|
|
|
|
|
|
|
my $time = localtime time; |
2352
|
|
|
|
|
|
|
$class->log->info("*** Request $COUNT ($av/s) [$$] [$time] ***"); |
2353
|
|
|
|
|
|
|
} |
2354
|
|
|
|
|
|
|
|
2355
|
|
|
|
|
|
|
my $c = $class->prepare(@arguments); |
2356
|
203
|
100
|
66
|
|
|
1016
|
$c->dispatch; |
|
|
|
66
|
|
|
|
|
|
|
|
100
|
|
|
|
|
2357
|
|
|
|
|
|
|
$status = $c->finalize; |
2358
|
|
|
|
|
|
|
} catch { |
2359
|
|
|
|
|
|
|
#rethow if this can be handled by middleware |
2360
|
|
|
|
|
|
|
if ( $class->_handle_http_exception($_) ) { |
2361
|
|
|
|
|
|
|
$_->can('rethrow') ? $_->rethrow : croak $_; |
2362
|
|
|
|
|
|
|
} |
2363
|
|
|
|
|
|
|
chomp(my $error = $_); |
2364
|
|
|
|
|
|
|
$class->log->error(qq/Caught exception in engine "$error"/); |
2365
|
|
|
|
|
|
|
}; |
2366
|
|
|
|
|
|
|
|
2367
|
|
|
|
|
|
|
$COUNT++; |
2368
|
|
|
|
|
|
|
|
2369
|
|
|
|
|
|
|
if(my $coderef = $class->log->can('_flush')){ |
2370
|
|
|
|
|
|
|
$class->log->$coderef(); |
2371
|
|
|
|
|
|
|
} |
2372
|
0
|
|
|
0
|
1
|
0
|
return $status; |
|
0
|
|
|
|
|
0
|
|
2373
|
|
|
|
|
|
|
} |
2374
|
|
|
|
|
|
|
|
2375
|
|
|
|
|
|
|
=head2 $class->prepare( @arguments ) |
2376
|
|
|
|
|
|
|
|
2377
|
|
|
|
|
|
|
Creates a Catalyst context from an engine-specific request (Apache, CGI, |
2378
|
|
|
|
|
|
|
etc.). |
2379
|
|
|
|
|
|
|
|
2380
|
920
|
|
|
920
|
1
|
2120
|
=cut |
|
920
|
|
|
|
|
2562
|
|
2381
|
|
|
|
|
|
|
|
2382
|
|
|
|
|
|
|
has _uploadtmp => ( |
2383
|
|
|
|
|
|
|
is => 'ro', |
2384
|
|
|
|
|
|
|
predicate => '_has_uploadtmp', |
2385
|
|
|
|
|
|
|
); |
2386
|
|
|
|
|
|
|
|
2387
|
|
|
|
|
|
|
my ( $class, @arguments ) = @_; |
2388
|
7765
|
|
|
7765
|
1
|
13613
|
|
|
7765
|
|
|
|
|
21443
|
|
2389
|
|
|
|
|
|
|
# XXX |
2390
|
|
|
|
|
|
|
# After the app/ctxt split, this should become an attribute based on something passed |
2391
|
|
|
|
|
|
|
# into the application. |
2392
|
|
|
|
|
|
|
$class->context_class( ref $class || $class ) unless $class->context_class; |
2393
|
|
|
|
|
|
|
|
2394
|
|
|
|
|
|
|
my $uploadtmp = $class->config->{uploadtmp}; |
2395
|
|
|
|
|
|
|
my $c = $class->context_class->new({ $uploadtmp ? (_uploadtmp => $uploadtmp) : ()}); |
2396
|
|
|
|
|
|
|
|
2397
|
2907
|
|
|
2907
|
1
|
5436
|
$c->response->_context($c); |
|
2907
|
|
|
|
|
8351
|
|
2398
|
|
|
|
|
|
|
$c->stats($class->stats_class->new)->enable($c->use_stats); |
2399
|
|
|
|
|
|
|
|
2400
|
|
|
|
|
|
|
if ( $c->debug || $c->config->{enable_catalyst_header} ) { |
2401
|
|
|
|
|
|
|
$c->res->headers->header( 'X-Catalyst' => $Catalyst::VERSION ); |
2402
|
|
|
|
|
|
|
} |
2403
|
|
|
|
|
|
|
|
2404
|
|
|
|
|
|
|
try { |
2405
|
|
|
|
|
|
|
# Allow engine to direct the prepare flow (for POE) |
2406
|
925
|
|
|
925
|
1
|
3384
|
if ( my $prepare = $c->engine->can('prepare') ) { |
2407
|
|
|
|
|
|
|
$c->engine->$prepare( $c, @arguments ); |
2408
|
|
|
|
|
|
|
} |
2409
|
925
|
|
|
|
|
2252
|
else { |
2410
|
|
|
|
|
|
|
$c->prepare_request(@arguments); |
2411
|
925
|
100
|
|
925
|
|
35015
|
$c->prepare_connection; |
2412
|
16
|
|
50
|
|
|
114
|
$c->prepare_query_parameters; |
2413
|
16
|
|
|
|
|
158
|
$c->prepare_headers; # Just hooks, no longer needed - they just |
2414
|
16
|
|
|
|
|
808
|
$c->prepare_cookies; # cause the lazy attribute on req to build |
2415
|
16
|
|
|
|
|
108
|
$c->prepare_path; |
2416
|
|
|
|
|
|
|
|
2417
|
|
|
|
|
|
|
# Prepare the body for reading, either by prepare_body |
2418
|
925
|
|
|
|
|
5017
|
# or the user, if they are using $c->read |
2419
|
920
|
|
|
|
|
45514
|
$c->prepare_read; |
2420
|
916
|
|
|
|
|
6484
|
|
2421
|
|
|
|
|
|
|
# Parse the body unless the user wants it on-demand |
2422
|
|
|
|
|
|
|
unless ( ref($c)->config->{parse_on_demand} ) { |
2423
|
8
|
100
|
|
8
|
|
368
|
$c->prepare_body; |
2424
|
4
|
50
|
|
|
|
104
|
} |
2425
|
|
|
|
|
|
|
} |
2426
|
4
|
|
|
|
|
18
|
$c->prepare_action; |
2427
|
4
|
|
|
|
|
19
|
} |
2428
|
925
|
|
|
|
|
7787
|
# VERY ugly and probably shouldn't rely on ->finalize actually working |
2429
|
|
|
|
|
|
|
catch { |
2430
|
920
|
|
|
|
|
21202
|
# failed prepare is always due to an invalid request, right? |
2431
|
|
|
|
|
|
|
# Note we call finalize and then die here, which escapes |
2432
|
920
|
100
|
|
|
|
5139
|
# finalize being called in the enclosing block.. |
2433
|
869
|
|
|
|
|
3028
|
# It in fact couldn't be called, as we don't return $c.. |
2434
|
|
|
|
|
|
|
# This is a mess - but I'm unsure you can fix this without |
2435
|
920
|
|
|
|
|
4611
|
# breaking compat for people doing crazy things (we should set |
2436
|
|
|
|
|
|
|
# the 400 and just return the ctx here IMO, letting finalize get called |
2437
|
|
|
|
|
|
|
# above... |
2438
|
|
|
|
|
|
|
if ( $c->_handle_http_exception($_) ) { |
2439
|
|
|
|
|
|
|
foreach my $err (@{$c->error}) { |
2440
|
|
|
|
|
|
|
$c->log->error($err); |
2441
|
|
|
|
|
|
|
} |
2442
|
|
|
|
|
|
|
$c->clear_errors; |
2443
|
|
|
|
|
|
|
$c->log->_flush if $c->log->can('_flush'); |
2444
|
|
|
|
|
|
|
$_->can('rethrow') ? $_->rethrow : croak $_; |
2445
|
|
|
|
|
|
|
} else { |
2446
|
|
|
|
|
|
|
$c->response->status(400); |
2447
|
|
|
|
|
|
|
$c->response->content_type('text/plain'); |
2448
|
|
|
|
|
|
|
$c->response->body('Bad Request'); |
2449
|
|
|
|
|
|
|
$c->finalize; |
2450
|
|
|
|
|
|
|
die $_; |
2451
|
925
|
|
|
925
|
1
|
23273
|
} |
2452
|
|
|
|
|
|
|
}; |
2453
|
|
|
|
|
|
|
|
2454
|
|
|
|
|
|
|
$c->log_request; |
2455
|
|
|
|
|
|
|
$c->{stash} = $c->stash; |
2456
|
925
|
100
|
33
|
|
|
4652
|
Scalar::Util::weaken($c->{stash}); |
2457
|
|
|
|
|
|
|
|
2458
|
925
|
|
|
|
|
3863
|
return $c; |
2459
|
925
|
100
|
|
|
|
3561
|
} |
2460
|
|
|
|
|
|
|
|
2461
|
925
|
|
|
|
|
117697
|
=head2 $c->prepare_action |
2462
|
925
|
|
|
|
|
5766
|
|
2463
|
|
|
|
|
|
|
Prepares action. See L<Catalyst::Dispatcher>. |
2464
|
925
|
100
|
66
|
|
|
3797
|
|
2465
|
16
|
|
|
|
|
175
|
=cut |
2466
|
|
|
|
|
|
|
|
2467
|
|
|
|
|
|
|
my $c = shift; |
2468
|
|
|
|
|
|
|
my $ret = $c->dispatcher->prepare_action( $c, @_); |
2469
|
|
|
|
|
|
|
|
2470
|
925
|
50
|
|
925
|
|
42678
|
if($c->encoding) { |
2471
|
0
|
|
|
|
|
0
|
foreach (@{$c->req->arguments}, @{$c->req->captures}) { |
2472
|
|
|
|
|
|
|
$_ = $c->_handle_param_unicode_decoding($_); |
2473
|
|
|
|
|
|
|
} |
2474
|
925
|
|
|
|
|
4718
|
} |
2475
|
925
|
|
|
|
|
4710
|
|
2476
|
925
|
|
|
|
|
4536
|
return $ret; |
2477
|
924
|
|
|
|
|
17502
|
} |
2478
|
924
|
|
|
|
|
4281
|
|
2479
|
924
|
|
|
|
|
4765
|
|
2480
|
|
|
|
|
|
|
=head2 $c->prepare_body |
2481
|
|
|
|
|
|
|
|
2482
|
|
|
|
|
|
|
Prepares message body. |
2483
|
924
|
|
|
|
|
4548
|
|
2484
|
|
|
|
|
|
|
=cut |
2485
|
|
|
|
|
|
|
|
2486
|
924
|
100
|
|
|
|
4518
|
my $c = shift; |
2487
|
921
|
|
|
|
|
4167
|
|
2488
|
|
|
|
|
|
|
return if $c->request->_has_body; |
2489
|
|
|
|
|
|
|
|
2490
|
922
|
|
|
|
|
5406
|
# Initialize on-demand data |
2491
|
|
|
|
|
|
|
$c->engine->prepare_body( $c, @_ ); |
2492
|
|
|
|
|
|
|
$c->prepare_parameters; |
2493
|
|
|
|
|
|
|
$c->prepare_uploads; |
2494
|
|
|
|
|
|
|
} |
2495
|
|
|
|
|
|
|
|
2496
|
|
|
|
|
|
|
=head2 $c->prepare_body_chunk( $chunk ) |
2497
|
|
|
|
|
|
|
|
2498
|
|
|
|
|
|
|
Prepares a chunk of data before sending it to L<HTTP::Body>. |
2499
|
|
|
|
|
|
|
|
2500
|
|
|
|
|
|
|
See L<Catalyst::Engine>. |
2501
|
|
|
|
|
|
|
|
2502
|
5
|
100
|
|
5
|
|
147
|
=cut |
2503
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
5
|
|
2504
|
0
|
|
|
|
|
0
|
my $c = shift; |
2505
|
|
|
|
|
|
|
$c->engine->prepare_body_chunk( $c, @_ ); |
2506
|
1
|
|
|
|
|
8
|
} |
2507
|
1
|
50
|
|
|
|
4
|
|
2508
|
1
|
50
|
|
|
|
39
|
=head2 $c->prepare_body_parameters |
2509
|
|
|
|
|
|
|
|
2510
|
4
|
|
|
|
|
116
|
Prepares body parameters. |
2511
|
4
|
|
|
|
|
85
|
|
2512
|
4
|
|
|
|
|
158
|
=cut |
2513
|
4
|
|
|
|
|
16
|
|
2514
|
4
|
|
|
|
|
38
|
my $c = shift; |
2515
|
|
|
|
|
|
|
$c->request->prepare_body_parameters( $c, @_ ); |
2516
|
925
|
|
|
|
|
11847
|
} |
2517
|
|
|
|
|
|
|
|
2518
|
920
|
|
|
|
|
71578
|
=head2 $c->prepare_connection |
2519
|
920
|
|
|
|
|
3920
|
|
2520
|
920
|
|
|
|
|
3955
|
Prepares connection. |
2521
|
|
|
|
|
|
|
|
2522
|
920
|
|
|
|
|
3445
|
=cut |
2523
|
|
|
|
|
|
|
|
2524
|
|
|
|
|
|
|
my $c = shift; |
2525
|
|
|
|
|
|
|
$c->request->prepare_connection($c); |
2526
|
|
|
|
|
|
|
} |
2527
|
|
|
|
|
|
|
|
2528
|
|
|
|
|
|
|
=head2 $c->prepare_cookies |
2529
|
|
|
|
|
|
|
|
2530
|
|
|
|
|
|
|
Prepares cookies by ensuring that the attribute on the request |
2531
|
|
|
|
|
|
|
object has been built. |
2532
|
922
|
|
|
922
|
1
|
7602
|
|
2533
|
922
|
|
|
|
|
4319
|
=cut |
2534
|
|
|
|
|
|
|
|
2535
|
922
|
100
|
|
|
|
3117
|
|
2536
|
921
|
|
|
|
|
1870
|
=head2 $c->prepare_headers |
|
921
|
|
|
|
|
2817
|
|
|
921
|
|
|
|
|
2783
|
|
2537
|
780
|
|
|
|
|
8148
|
|
2538
|
|
|
|
|
|
|
Prepares request headers by ensuring that the attribute on the request |
2539
|
|
|
|
|
|
|
object has been built. |
2540
|
|
|
|
|
|
|
|
2541
|
920
|
|
|
|
|
13674
|
=cut |
2542
|
|
|
|
|
|
|
|
2543
|
|
|
|
|
|
|
|
2544
|
|
|
|
|
|
|
=head2 $c->prepare_parameters |
2545
|
|
|
|
|
|
|
|
2546
|
|
|
|
|
|
|
Prepares parameters. |
2547
|
|
|
|
|
|
|
|
2548
|
|
|
|
|
|
|
=cut |
2549
|
|
|
|
|
|
|
|
2550
|
|
|
|
|
|
|
my $c = shift; |
2551
|
|
|
|
|
|
|
$c->prepare_body_parameters; |
2552
|
1023
|
|
|
1023
|
1
|
3706
|
$c->engine->prepare_parameters( $c, @_ ); |
2553
|
|
|
|
|
|
|
} |
2554
|
1023
|
100
|
|
|
|
28083
|
|
2555
|
|
|
|
|
|
|
=head2 $c->prepare_path |
2556
|
|
|
|
|
|
|
|
2557
|
922
|
|
|
|
|
3565
|
Prepares path and base. |
2558
|
921
|
|
|
|
|
4294
|
|
2559
|
920
|
|
|
|
|
3968
|
=cut |
2560
|
|
|
|
|
|
|
|
2561
|
|
|
|
|
|
|
|
2562
|
|
|
|
|
|
|
=head2 $c->prepare_query_parameters |
2563
|
|
|
|
|
|
|
|
2564
|
|
|
|
|
|
|
Prepares query parameters. |
2565
|
|
|
|
|
|
|
|
2566
|
|
|
|
|
|
|
=cut |
2567
|
|
|
|
|
|
|
|
2568
|
|
|
|
|
|
|
my $c = shift; |
2569
|
|
|
|
|
|
|
|
2570
|
|
|
|
|
|
|
$c->engine->prepare_query_parameters( $c, @_ ); |
2571
|
0
|
|
|
0
|
1
|
0
|
} |
2572
|
0
|
|
|
|
|
0
|
|
2573
|
|
|
|
|
|
|
=head2 $c->log_request |
2574
|
|
|
|
|
|
|
|
2575
|
|
|
|
|
|
|
Writes information about the request to the debug logs. This includes: |
2576
|
|
|
|
|
|
|
|
2577
|
|
|
|
|
|
|
=over 4 |
2578
|
|
|
|
|
|
|
|
2579
|
|
|
|
|
|
|
=item * Request method, path, and remote IP address |
2580
|
|
|
|
|
|
|
|
2581
|
|
|
|
|
|
|
=item * Query keywords (see L<Catalyst::Request/query_keywords>) |
2582
|
922
|
|
|
922
|
1
|
1853
|
|
2583
|
922
|
|
|
|
|
21645
|
=item * Request parameters |
2584
|
|
|
|
|
|
|
|
2585
|
|
|
|
|
|
|
=item * File uploads |
2586
|
|
|
|
|
|
|
|
2587
|
|
|
|
|
|
|
=back |
2588
|
|
|
|
|
|
|
|
2589
|
|
|
|
|
|
|
=cut |
2590
|
|
|
|
|
|
|
|
2591
|
|
|
|
|
|
|
my $c = shift; |
2592
|
|
|
|
|
|
|
|
2593
|
925
|
|
|
925
|
1
|
2003
|
return unless $c->debug; |
2594
|
925
|
|
|
|
|
22312
|
|
2595
|
|
|
|
|
|
|
my($dump) = grep {$_->[0] eq 'Request' } $c->dump_these; |
2596
|
|
|
|
|
|
|
my $request = $dump->[1]; |
2597
|
|
|
|
|
|
|
|
2598
|
|
|
|
|
|
|
my ( $method, $path, $address ) = ( $request->method, $request->path, $request->address ); |
2599
|
|
|
|
|
|
|
$method ||= ''; |
2600
|
|
|
|
|
|
|
$path = '/' unless length $path; |
2601
|
|
|
|
|
|
|
$address ||= ''; |
2602
|
|
|
|
|
|
|
|
2603
|
|
|
|
|
|
|
$path =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg; |
2604
|
924
|
|
|
924
|
1
|
1961
|
$path = decode_utf8($path); |
|
924
|
|
|
|
|
23437
|
|
2605
|
|
|
|
|
|
|
|
2606
|
|
|
|
|
|
|
$c->log->debug(qq/"$method" request for "$path" from "$address"/); |
2607
|
|
|
|
|
|
|
|
2608
|
|
|
|
|
|
|
$c->log_request_headers($request->headers); |
2609
|
|
|
|
|
|
|
|
2610
|
|
|
|
|
|
|
if ( my $keywords = $request->query_keywords ) { |
2611
|
|
|
|
|
|
|
$c->log->debug("Query keywords are: $keywords"); |
2612
|
|
|
|
|
|
|
} |
2613
|
924
|
|
|
924
|
1
|
2077
|
|
|
924
|
|
|
|
|
23245
|
|
2614
|
|
|
|
|
|
|
$c->log_request_parameters( query => $request->query_parameters, $request->_has_body ? (body => $request->body_parameters) : () ); |
2615
|
|
|
|
|
|
|
|
2616
|
|
|
|
|
|
|
$c->log_request_uploads($request); |
2617
|
|
|
|
|
|
|
} |
2618
|
|
|
|
|
|
|
|
2619
|
|
|
|
|
|
|
=head2 $c->log_response |
2620
|
|
|
|
|
|
|
|
2621
|
|
|
|
|
|
|
Writes information about the response to the debug logs by calling |
2622
|
922
|
|
|
922
|
1
|
2040
|
C<< $c->log_response_status_line >> and C<< $c->log_response_headers >>. |
2623
|
922
|
|
|
|
|
4034
|
|
2624
|
921
|
|
|
|
|
3552
|
=cut |
2625
|
|
|
|
|
|
|
|
2626
|
|
|
|
|
|
|
my $c = shift; |
2627
|
|
|
|
|
|
|
|
2628
|
|
|
|
|
|
|
return unless $c->debug; |
2629
|
|
|
|
|
|
|
|
2630
|
|
|
|
|
|
|
my($dump) = grep {$_->[0] eq 'Response' } $c->dump_these; |
2631
|
|
|
|
|
|
|
my $response = $dump->[1]; |
2632
|
|
|
|
|
|
|
|
2633
|
924
|
|
|
924
|
1
|
2076
|
$c->log_response_status_line($response); |
|
924
|
|
|
|
|
4717
|
|
2634
|
|
|
|
|
|
|
$c->log_response_headers($response->headers); |
2635
|
|
|
|
|
|
|
} |
2636
|
|
|
|
|
|
|
|
2637
|
|
|
|
|
|
|
=head2 $c->log_response_status_line($response) |
2638
|
|
|
|
|
|
|
|
2639
|
|
|
|
|
|
|
Writes one line of information about the response to the debug logs. This includes: |
2640
|
|
|
|
|
|
|
|
2641
|
|
|
|
|
|
|
=over 4 |
2642
|
925
|
|
|
925
|
1
|
2147
|
|
2643
|
|
|
|
|
|
|
=item * Response status code |
2644
|
925
|
|
|
|
|
3281
|
|
2645
|
|
|
|
|
|
|
=item * Content-Type header (if present) |
2646
|
|
|
|
|
|
|
|
2647
|
|
|
|
|
|
|
=item * Content-Length header (if present) |
2648
|
|
|
|
|
|
|
|
2649
|
|
|
|
|
|
|
=back |
2650
|
|
|
|
|
|
|
|
2651
|
|
|
|
|
|
|
=cut |
2652
|
|
|
|
|
|
|
|
2653
|
|
|
|
|
|
|
my ($c, $response) = @_; |
2654
|
|
|
|
|
|
|
|
2655
|
|
|
|
|
|
|
$c->log->debug( |
2656
|
|
|
|
|
|
|
sprintf( |
2657
|
|
|
|
|
|
|
'Response Code: %s; Content-Type: %s; Content-Length: %s', |
2658
|
|
|
|
|
|
|
$response->status || 'unknown', |
2659
|
|
|
|
|
|
|
$response->headers->header('Content-Type') || 'unknown', |
2660
|
|
|
|
|
|
|
$response->headers->header('Content-Length') || 'unknown' |
2661
|
|
|
|
|
|
|
) |
2662
|
|
|
|
|
|
|
); |
2663
|
|
|
|
|
|
|
} |
2664
|
|
|
|
|
|
|
|
2665
|
|
|
|
|
|
|
=head2 $c->log_response_headers($headers); |
2666
|
920
|
|
|
920
|
1
|
2236
|
|
2667
|
|
|
|
|
|
|
Hook method which can be wrapped by plugins to log the response headers. |
2668
|
920
|
100
|
|
|
|
2747
|
No-op in the default implementation. |
2669
|
|
|
|
|
|
|
|
2670
|
16
|
|
|
|
|
112
|
=cut |
|
64
|
|
|
|
|
159
|
|
2671
|
16
|
|
|
|
|
46
|
|
2672
|
|
|
|
|
|
|
|
2673
|
16
|
|
|
|
|
489
|
=head2 $c->log_request_parameters( query => {}, body => {} ) |
2674
|
16
|
|
50
|
|
|
57
|
|
2675
|
16
|
100
|
|
|
|
64
|
Logs request parameters to debug logs |
2676
|
16
|
|
50
|
|
|
48
|
|
2677
|
|
|
|
|
|
|
=cut |
2678
|
16
|
|
|
|
|
46
|
|
|
0
|
|
|
|
|
0
|
|
2679
|
16
|
|
|
|
|
154
|
my $c = shift; |
2680
|
|
|
|
|
|
|
my %all_params = @_; |
2681
|
16
|
|
|
|
|
147
|
|
2682
|
|
|
|
|
|
|
return unless $c->debug; |
2683
|
16
|
|
|
|
|
443
|
|
2684
|
|
|
|
|
|
|
my $column_width = Catalyst::Utils::term_width() - 44; |
2685
|
16
|
50
|
|
|
|
485
|
foreach my $type (qw(query body)) { |
2686
|
0
|
|
|
|
|
0
|
my $params = $all_params{$type}; |
2687
|
|
|
|
|
|
|
next if ! keys %$params; |
2688
|
|
|
|
|
|
|
my $t = Text::SimpleTable->new( [ 35, 'Parameter' ], [ $column_width, 'Value' ] ); |
2689
|
16
|
50
|
|
|
|
429
|
for my $key ( sort keys %$params ) { |
2690
|
|
|
|
|
|
|
my @values = (); |
2691
|
16
|
|
|
|
|
76
|
if(ref $params eq 'Hash::MultiValue') { |
2692
|
|
|
|
|
|
|
@values = $params->get_all($key); |
2693
|
|
|
|
|
|
|
} else { |
2694
|
|
|
|
|
|
|
my $param = $params->{$key}; |
2695
|
|
|
|
|
|
|
if( defined($param) ) { |
2696
|
|
|
|
|
|
|
@values = ref $param eq 'ARRAY' ? @$param : $param; |
2697
|
|
|
|
|
|
|
} |
2698
|
|
|
|
|
|
|
} |
2699
|
|
|
|
|
|
|
$t->row( $key.( scalar @values > 1 ? ' [multiple]' : ''), join(', ', @values) ); |
2700
|
|
|
|
|
|
|
} |
2701
|
|
|
|
|
|
|
$c->log->debug( ucfirst($type) . " Parameters are:\n" . $t->draw ); |
2702
|
920
|
|
|
920
|
1
|
1959
|
} |
2703
|
|
|
|
|
|
|
} |
2704
|
920
|
100
|
|
|
|
3022
|
|
2705
|
|
|
|
|
|
|
=head2 $c->log_request_uploads |
2706
|
13
|
|
|
|
|
86
|
|
|
52
|
|
|
|
|
125
|
|
2707
|
13
|
|
|
|
|
42
|
Logs file uploads included in the request to the debug logs. |
2708
|
|
|
|
|
|
|
The parameter name, filename, file type, and file size are all included in |
2709
|
13
|
|
|
|
|
82
|
the debug logs. |
2710
|
13
|
|
|
|
|
101
|
|
2711
|
|
|
|
|
|
|
=cut |
2712
|
|
|
|
|
|
|
|
2713
|
|
|
|
|
|
|
my $c = shift; |
2714
|
|
|
|
|
|
|
my $request = shift; |
2715
|
|
|
|
|
|
|
return unless $c->debug; |
2716
|
|
|
|
|
|
|
my $uploads = $request->uploads; |
2717
|
|
|
|
|
|
|
if ( keys %$uploads ) { |
2718
|
|
|
|
|
|
|
my $t = Text::SimpleTable->new( |
2719
|
|
|
|
|
|
|
[ 12, 'Parameter' ], |
2720
|
|
|
|
|
|
|
[ 26, 'Filename' ], |
2721
|
|
|
|
|
|
|
[ 18, 'Type' ], |
2722
|
|
|
|
|
|
|
[ 9, 'Size' ] |
2723
|
|
|
|
|
|
|
); |
2724
|
|
|
|
|
|
|
for my $key ( sort keys %$uploads ) { |
2725
|
|
|
|
|
|
|
my $upload = $uploads->{$key}; |
2726
|
|
|
|
|
|
|
for my $u ( ref $upload eq 'ARRAY' ? @{$upload} : ($upload) ) { |
2727
|
|
|
|
|
|
|
$t->row( $key, $u->filename, $u->type, $u->size ); |
2728
|
|
|
|
|
|
|
} |
2729
|
|
|
|
|
|
|
} |
2730
|
13
|
|
|
13
|
1
|
41
|
$c->log->debug( "File Uploads are:\n" . $t->draw ); |
2731
|
|
|
|
|
|
|
} |
2732
|
13
|
|
50
|
|
|
55
|
} |
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
2733
|
|
|
|
|
|
|
|
2734
|
|
|
|
|
|
|
=head2 $c->log_request_headers($headers); |
2735
|
|
|
|
|
|
|
|
2736
|
|
|
|
|
|
|
Hook method which can be wrapped by plugins to log the request headers. |
2737
|
|
|
|
|
|
|
No-op in the default implementation. |
2738
|
|
|
|
|
|
|
|
2739
|
|
|
|
|
|
|
=cut |
2740
|
|
|
|
|
|
|
|
2741
|
|
|
|
|
|
|
|
2742
|
|
|
|
|
|
|
=head2 $c->log_headers($type => $headers) |
2743
|
|
|
|
|
|
|
|
2744
|
|
|
|
|
|
|
Logs L<HTTP::Headers> (either request or response) to the debug logs. |
2745
|
|
|
|
|
|
|
|
2746
|
|
|
|
|
|
|
=cut |
2747
|
|
|
|
|
|
|
|
2748
|
|
|
|
|
|
|
my $c = shift; |
2749
|
|
|
|
13
|
1
|
|
my $type = shift; |
2750
|
|
|
|
|
|
|
my $headers = shift; # an HTTP::Headers instance |
2751
|
|
|
|
|
|
|
|
2752
|
|
|
|
|
|
|
return unless $c->debug; |
2753
|
|
|
|
|
|
|
|
2754
|
|
|
|
|
|
|
my $column_width = Catalyst::Utils::term_width() - 28; |
2755
|
|
|
|
|
|
|
my $t = Text::SimpleTable->new( [ 15, 'Header Name' ], [ $column_width, 'Value' ] ); |
2756
|
|
|
|
|
|
|
$headers->scan( |
2757
|
|
|
|
|
|
|
sub { |
2758
|
16
|
|
|
16
|
1
|
38
|
my ( $name, $value ) = @_; |
2759
|
16
|
|
|
|
|
83
|
$t->row( $name, $value ); |
2760
|
|
|
|
|
|
|
} |
2761
|
16
|
50
|
|
|
|
64
|
); |
2762
|
|
|
|
|
|
|
$c->log->debug( ucfirst($type) . " Headers:\n" . $t->draw ); |
2763
|
16
|
|
|
|
|
110
|
} |
2764
|
16
|
|
|
|
|
63
|
|
2765
|
32
|
|
|
|
|
70
|
|
2766
|
32
|
50
|
|
|
|
141
|
=head2 $c->prepare_read |
2767
|
0
|
|
|
|
|
0
|
|
2768
|
0
|
|
|
|
|
0
|
Prepares the input for reading. |
2769
|
0
|
|
|
|
|
0
|
|
2770
|
0
|
0
|
|
|
|
0
|
=cut |
2771
|
0
|
|
|
|
|
0
|
|
2772
|
|
|
|
|
|
|
|
2773
|
0
|
|
|
|
|
0
|
=head2 $c->prepare_request |
2774
|
0
|
0
|
|
|
|
0
|
|
2775
|
0
|
0
|
|
|
|
0
|
Prepares the engine request. |
2776
|
|
|
|
|
|
|
|
2777
|
|
|
|
|
|
|
=cut |
2778
|
0
|
0
|
|
|
|
0
|
|
2779
|
|
|
|
|
|
|
|
2780
|
0
|
|
|
|
|
0
|
=head2 $c->prepare_uploads |
2781
|
|
|
|
|
|
|
|
2782
|
|
|
|
|
|
|
Prepares uploads. |
2783
|
|
|
|
|
|
|
|
2784
|
|
|
|
|
|
|
=cut |
2785
|
|
|
|
|
|
|
|
2786
|
|
|
|
|
|
|
my $c = shift; |
2787
|
|
|
|
|
|
|
$c->engine->prepare_uploads( $c, @_ ); |
2788
|
|
|
|
|
|
|
} |
2789
|
|
|
|
|
|
|
|
2790
|
|
|
|
|
|
|
=head2 $c->prepare_write |
2791
|
|
|
|
|
|
|
|
2792
|
|
|
|
|
|
|
Prepares the output for writing. |
2793
|
16
|
|
|
16
|
1
|
33
|
|
2794
|
16
|
|
|
|
|
29
|
=cut |
2795
|
16
|
50
|
|
|
|
61
|
|
2796
|
16
|
|
|
|
|
573
|
|
2797
|
16
|
50
|
|
|
|
203
|
=head2 $c->request_class |
2798
|
0
|
|
|
|
|
0
|
|
2799
|
|
|
|
|
|
|
Returns or sets the request class. Defaults to L<Catalyst::Request>. |
2800
|
|
|
|
|
|
|
|
2801
|
|
|
|
|
|
|
=head2 $app->request_class_traits |
2802
|
|
|
|
|
|
|
|
2803
|
|
|
|
|
|
|
An arrayref of L<Moose::Role>s which are applied to the request class. You can |
2804
|
0
|
|
|
|
|
0
|
name the full namespace of the role, or a namespace suffix, which will then |
2805
|
0
|
|
|
|
|
0
|
be tried against the following standard namespace prefixes. |
2806
|
0
|
0
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
2807
|
0
|
|
|
|
|
0
|
$MyApp::TraitFor::Request::$trait_suffix |
2808
|
|
|
|
|
|
|
Catalyst::TraitFor::Request::$trait_suffix |
2809
|
|
|
|
|
|
|
|
2810
|
0
|
|
|
|
|
0
|
So for example if you set: |
2811
|
|
|
|
|
|
|
|
2812
|
|
|
|
|
|
|
MyApp->request_class_traits(['Foo']); |
2813
|
|
|
|
|
|
|
|
2814
|
|
|
|
|
|
|
We try each possible role in turn (and throw an error if none load) |
2815
|
|
|
|
|
|
|
|
2816
|
|
|
|
|
|
|
Foo |
2817
|
|
|
|
|
|
|
MyApp::TraitFor::Request::Foo |
2818
|
|
|
|
|
|
|
Catalyst::TraitFor::Request::Foo |
2819
|
|
|
|
|
|
|
|
2820
|
|
|
|
|
|
|
The namespace part 'TraitFor::Request' was chosen to assist in backwards |
2821
|
|
|
|
16
|
1
|
|
compatibility with L<CatalystX::RoleApplicator> which previously provided |
2822
|
|
|
|
|
|
|
these features in a stand alone package. |
2823
|
|
|
|
|
|
|
|
2824
|
|
|
|
|
|
|
=head2 $app->composed_request_class |
2825
|
|
|
|
|
|
|
|
2826
|
|
|
|
|
|
|
This is the request class which has been composed with any request_class_traits. |
2827
|
|
|
|
|
|
|
|
2828
|
|
|
|
|
|
|
=head2 $c->response_class |
2829
|
|
|
|
|
|
|
|
2830
|
0
|
|
|
0
|
1
|
0
|
Returns or sets the response class. Defaults to L<Catalyst::Response>. |
2831
|
0
|
|
|
|
|
0
|
|
2832
|
0
|
|
|
|
|
0
|
=head2 $app->response_class_traits |
2833
|
|
|
|
|
|
|
|
2834
|
0
|
0
|
|
|
|
0
|
An arrayref of L<Moose::Role>s which are applied to the response class. You can |
2835
|
|
|
|
|
|
|
name the full namespace of the role, or a namespace suffix, which will then |
2836
|
0
|
|
|
|
|
0
|
be tried against the following standard namespace prefixes. |
2837
|
0
|
|
|
|
|
0
|
|
2838
|
|
|
|
|
|
|
$MyApp::TraitFor::Response::$trait_suffix |
2839
|
|
|
|
|
|
|
Catalyst::TraitFor::Response::$trait_suffix |
2840
|
0
|
|
|
0
|
|
0
|
|
2841
|
0
|
|
|
|
|
0
|
So for example if you set: |
2842
|
|
|
|
|
|
|
|
2843
|
0
|
|
|
|
|
0
|
MyApp->response_class_traits(['Foo']); |
2844
|
0
|
|
|
|
|
0
|
|
2845
|
|
|
|
|
|
|
We try each possible role in turn (and throw an error if none load) |
2846
|
|
|
|
|
|
|
|
2847
|
|
|
|
|
|
|
Foo |
2848
|
|
|
|
|
|
|
MyApp::TraitFor::Response::Foo |
2849
|
|
|
|
|
|
|
Catalyst::TraitFor::Responset::Foo |
2850
|
|
|
|
|
|
|
|
2851
|
|
|
|
|
|
|
The namespace part 'TraitFor::Response' was chosen to assist in backwards |
2852
|
|
|
|
|
|
|
compatibility with L<CatalystX::RoleApplicator> which previously provided |
2853
|
|
|
|
|
|
|
these features in a stand alone package. |
2854
|
924
|
|
|
924
|
1
|
2086
|
|
|
924
|
|
|
|
|
3331
|
|
2855
|
|
|
|
|
|
|
|
2856
|
|
|
|
|
|
|
=head2 $app->composed_response_class |
2857
|
|
|
|
|
|
|
|
2858
|
|
|
|
|
|
|
This is the request class which has been composed with any response_class_traits. |
2859
|
|
|
|
|
|
|
|
2860
|
|
|
|
|
|
|
=head2 $c->read( [$maxlength] ) |
2861
|
|
|
|
|
|
|
|
2862
|
925
|
|
|
925
|
1
|
2403
|
Reads a chunk of data from the request body. This method is designed to |
|
925
|
|
|
|
|
2720
|
|
2863
|
|
|
|
|
|
|
be used in a while loop, reading C<$maxlength> bytes on every call. |
2864
|
|
|
|
|
|
|
C<$maxlength> defaults to the size of the request if not specified. |
2865
|
|
|
|
|
|
|
|
2866
|
|
|
|
|
|
|
You have to set C<< MyApp->config(parse_on_demand => 1) >> to use this |
2867
|
|
|
|
|
|
|
directly. |
2868
|
|
|
|
|
|
|
|
2869
|
|
|
|
|
|
|
Warning: If you use read(), Catalyst will not process the body, |
2870
|
|
|
|
|
|
|
so you will not be able to access POST parameters or file uploads via |
2871
|
920
|
|
|
920
|
1
|
1988
|
$c->request. You must handle all body parsing yourself. |
2872
|
920
|
|
|
|
|
3214
|
|
2873
|
|
|
|
|
|
|
=cut |
2874
|
|
|
|
|
|
|
|
2875
|
|
|
|
|
|
|
|
2876
|
|
|
|
|
|
|
=head2 $c->run |
2877
|
|
|
|
|
|
|
|
2878
|
|
|
|
|
|
|
Starts the engine. |
2879
|
|
|
|
|
|
|
|
2880
|
|
|
|
|
|
|
=cut |
2881
|
0
|
|
|
0
|
1
|
0
|
|
|
0
|
|
|
|
|
0
|
|
2882
|
|
|
|
|
|
|
my $app = shift; |
2883
|
|
|
|
|
|
|
$app->_make_immutable_if_needed; |
2884
|
|
|
|
|
|
|
$app->engine_loader->needs_psgi_engine_compat_hack ? |
2885
|
|
|
|
|
|
|
$app->engine->run($app, @_) : |
2886
|
|
|
|
|
|
|
$app->engine->run( $app, $app->_finalized_psgi_app, @_ ); |
2887
|
|
|
|
|
|
|
} |
2888
|
|
|
|
|
|
|
|
2889
|
|
|
|
|
|
|
my $class = shift; |
2890
|
|
|
|
|
|
|
my $meta = find_meta($class); |
2891
|
|
|
|
|
|
|
my $isa_ca = $class->isa('Class::Accessor::Fast') || $class->isa('Class::Accessor'); |
2892
|
|
|
|
|
|
|
if ( |
2893
|
|
|
|
|
|
|
$meta->is_immutable |
2894
|
|
|
|
|
|
|
&& ! { $meta->immutable_options }->{replace_constructor} |
2895
|
|
|
|
|
|
|
&& $isa_ca |
2896
|
|
|
|
|
|
|
) { |
2897
|
|
|
|
|
|
|
warn("You made your application class ($class) immutable, " |
2898
|
|
|
|
|
|
|
. "but did not inline the\nconstructor. " |
2899
|
|
|
|
|
|
|
. "This will break catalyst, as your app \@ISA " |
2900
|
|
|
|
|
|
|
. "Class::Accessor(::Fast)?\nPlease pass " |
2901
|
|
|
|
|
|
|
. "(replace_constructor => 1)\nwhen making your class immutable.\n"); |
2902
|
|
|
|
|
|
|
} |
2903
|
|
|
|
|
|
|
unless ($meta->is_immutable) { |
2904
|
|
|
|
|
|
|
# XXX - FIXME warning here as you should make your app immutable yourself. |
2905
|
|
|
|
|
|
|
$meta->make_immutable( |
2906
|
|
|
|
|
|
|
replace_constructor => 1, |
2907
|
|
|
|
|
|
|
); |
2908
|
|
|
|
|
|
|
} |
2909
|
|
|
|
|
|
|
} |
2910
|
|
|
|
|
|
|
|
2911
|
|
|
|
|
|
|
=head2 $c->set_action( $action, $code, $namespace, $attrs ) |
2912
|
|
|
|
|
|
|
|
2913
|
|
|
|
|
|
|
Sets an action in a given namespace. |
2914
|
|
|
|
|
|
|
|
2915
|
|
|
|
|
|
|
=cut |
2916
|
|
|
|
|
|
|
|
2917
|
|
|
|
|
|
|
|
2918
|
|
|
|
|
|
|
=head2 $c->setup_actions($component) |
2919
|
|
|
|
|
|
|
|
2920
|
|
|
|
|
|
|
Sets up actions for a component. |
2921
|
|
|
|
|
|
|
|
2922
|
|
|
|
|
|
|
=cut |
2923
|
|
|
|
|
|
|
|
2924
|
|
|
|
|
|
|
|
2925
|
|
|
|
|
|
|
=head2 $c->setup_components |
2926
|
|
|
|
|
|
|
|
2927
|
|
|
|
|
|
|
This method is called internally to set up the application's components. |
2928
|
|
|
|
|
|
|
|
2929
|
|
|
|
|
|
|
It finds modules by calling the L<locate_components> method, expands them to |
2930
|
|
|
|
|
|
|
package names with the L<expand_component_module> method, and then installs |
2931
|
|
|
|
|
|
|
each component into the application. |
2932
|
|
|
|
|
|
|
|
2933
|
|
|
|
|
|
|
The C<setup_components> config option is passed to both of the above methods. |
2934
|
|
|
|
|
|
|
|
2935
|
|
|
|
|
|
|
Installation of each component is performed by the L<setup_component> method, |
2936
|
|
|
|
|
|
|
below. |
2937
|
|
|
|
|
|
|
|
2938
|
|
|
|
|
|
|
=cut |
2939
|
|
|
|
|
|
|
|
2940
|
|
|
|
|
|
|
my $class = shift; |
2941
|
|
|
|
|
|
|
|
2942
|
|
|
|
|
|
|
my $config = $class->config->{ setup_components }; |
2943
|
|
|
|
|
|
|
|
2944
|
|
|
|
|
|
|
my @comps = $class->locate_components($config); |
2945
|
|
|
|
|
|
|
|
2946
|
|
|
|
|
|
|
my $deprecatedcatalyst_component_names = grep { /::[CMV]::/ } @comps; |
2947
|
|
|
|
|
|
|
$class->log->warn(qq{Your application is using the deprecated ::[MVC]:: type naming scheme.\n}. |
2948
|
|
|
|
|
|
|
qq{Please switch your class names to ::Model::, ::View:: and ::Controller: as appropriate.\n} |
2949
|
|
|
|
|
|
|
) if $deprecatedcatalyst_component_names; |
2950
|
|
|
|
|
|
|
|
2951
|
|
|
|
|
|
|
for my $component ( @comps ) { |
2952
|
|
|
|
|
|
|
|
2953
|
|
|
|
|
|
|
# We pass ignore_loaded here so that overlay files for (e.g.) |
2954
|
|
|
|
|
|
|
# Model::DBI::Schema sub-classes are loaded - if it's in @comps |
2955
|
|
|
|
|
|
|
# we know M::P::O found a file on disk so this is safe |
2956
|
|
|
|
|
|
|
|
2957
|
|
|
|
|
|
|
Catalyst::Utils::ensure_class_loaded( $component, { ignore_loaded => 1 } ); |
2958
|
|
|
|
|
|
|
} |
2959
|
|
|
|
|
|
|
|
2960
|
|
|
|
|
|
|
for my $component (@comps) { |
2961
|
12
|
|
|
12
|
1
|
85
|
my $instance = $class->components->{ $component } = $class->delayed_setup_component($component); |
|
12
|
|
|
|
|
286
|
|
2962
|
|
|
|
|
|
|
} |
2963
|
|
|
|
|
|
|
|
2964
|
|
|
|
|
|
|
# Inject a component or wrap a stand alone class in an adaptor. This makes a list |
2965
|
|
|
|
|
|
|
# of named components in the configuration that are not actually existing (not a |
2966
|
|
|
|
|
|
|
# real file). |
2967
|
|
|
|
|
|
|
|
2968
|
|
|
|
|
|
|
my @injected = $class->setup_injected_components; |
2969
|
|
|
|
|
|
|
|
2970
|
1
|
|
|
1
|
1
|
51
|
# All components are registered, now we need to 'init' them. |
2971
|
1
|
|
|
|
|
8
|
foreach my $component_name (@comps, @injected) { |
2972
|
1
|
50
|
|
|
|
442
|
$class->components->{$component_name} = $class->components->{$component_name}->() if |
2973
|
|
|
|
|
|
|
(ref($class->components->{$component_name}) || '') eq 'CODE'; |
2974
|
|
|
|
|
|
|
} |
2975
|
|
|
|
|
|
|
} |
2976
|
|
|
|
|
|
|
|
2977
|
|
|
|
|
|
|
=head2 $app->setup_injected_components |
2978
|
3
|
|
|
3
|
|
123
|
|
2979
|
3
|
|
|
|
|
19
|
Called by setup_compoents to setup components that are injected. |
2980
|
3
|
|
66
|
|
|
73
|
|
2981
|
3
|
50
|
66
|
|
|
23
|
=cut |
|
|
|
66
|
|
|
|
|
2982
|
|
|
|
|
|
|
|
2983
|
|
|
|
|
|
|
my ($class) = @_; |
2984
|
|
|
|
|
|
|
my @injected_components = keys %{$class->config->{inject_components} ||+{}}; |
2985
|
|
|
|
|
|
|
|
2986
|
1
|
|
|
|
|
52
|
foreach my $injected_comp_name(@injected_components) { |
2987
|
|
|
|
|
|
|
$class->setup_injected_component( |
2988
|
|
|
|
|
|
|
$injected_comp_name, |
2989
|
|
|
|
|
|
|
$class->config->{inject_components}->{$injected_comp_name}); |
2990
|
|
|
|
|
|
|
} |
2991
|
|
|
|
|
|
|
|
2992
|
3
|
100
|
|
|
|
27
|
return map { $class ."::" . $_ } |
2993
|
|
|
|
|
|
|
@injected_components; |
2994
|
2
|
|
|
|
|
18
|
} |
2995
|
|
|
|
|
|
|
|
2996
|
|
|
|
|
|
|
=head2 $app->setup_injected_component( $injected_component_name, $config ) |
2997
|
|
|
|
|
|
|
|
2998
|
|
|
|
|
|
|
Setup a given injected component. |
2999
|
|
|
|
|
|
|
|
3000
|
|
|
|
|
|
|
=cut |
3001
|
|
|
|
|
|
|
|
3002
|
|
|
|
|
|
|
my ($class, $injected_comp_name, $config) = @_; |
3003
|
|
|
|
|
|
|
if(my $component_class = $config->{from_component}) { |
3004
|
|
|
|
|
|
|
my @roles = @{$config->{roles} ||[]}; |
3005
|
|
|
|
|
|
|
Catalyst::Utils::inject_component( |
3006
|
0
|
|
|
0
|
1
|
0
|
into => $class, |
|
0
|
|
|
|
|
0
|
|
3007
|
|
|
|
|
|
|
component => $component_class, |
3008
|
|
|
|
|
|
|
(scalar(@roles) ? (traits => \@roles) : ()), |
3009
|
|
|
|
|
|
|
as => $injected_comp_name); |
3010
|
|
|
|
|
|
|
} |
3011
|
|
|
|
|
|
|
} |
3012
|
|
|
|
|
|
|
|
3013
|
|
|
|
|
|
|
=head2 $app->inject_component($MyApp_Component_name => \%args); |
3014
|
168
|
|
|
168
|
1
|
5930
|
|
|
168
|
|
|
|
|
1433
|
|
3015
|
|
|
|
|
|
|
Add a component that is injected at setup: |
3016
|
|
|
|
|
|
|
|
3017
|
|
|
|
|
|
|
MyApp->inject_component( 'Model::Foo' => { from_component => 'Common::Foo' } ); |
3018
|
|
|
|
|
|
|
|
3019
|
|
|
|
|
|
|
Must be called before ->setup. Expects a component name for your |
3020
|
|
|
|
|
|
|
current application and \%args where |
3021
|
|
|
|
|
|
|
|
3022
|
|
|
|
|
|
|
=over 4 |
3023
|
|
|
|
|
|
|
|
3024
|
|
|
|
|
|
|
=item from_component |
3025
|
|
|
|
|
|
|
|
3026
|
|
|
|
|
|
|
The target component being injected into your application |
3027
|
|
|
|
|
|
|
|
3028
|
|
|
|
|
|
|
=item roles |
3029
|
|
|
|
|
|
|
|
3030
|
|
|
|
|
|
|
An arrayref of L<Moose::Role>s that are applied to your component. |
3031
|
|
|
|
|
|
|
|
3032
|
163
|
|
|
163
|
1
|
486
|
=back |
3033
|
|
|
|
|
|
|
|
3034
|
163
|
|
|
|
|
682
|
Example |
3035
|
|
|
|
|
|
|
|
3036
|
163
|
|
|
|
|
3784
|
MyApp->inject_component( |
3037
|
|
|
|
|
|
|
'Model::Foo' => { |
3038
|
163
|
|
|
|
|
625
|
from_component => 'Common::Model::Foo', |
|
6696
|
|
|
|
|
14879
|
|
3039
|
163
|
100
|
|
|
|
859
|
roles => ['Role1', 'Role2'], |
3040
|
|
|
|
|
|
|
}); |
3041
|
|
|
|
|
|
|
|
3042
|
|
|
|
|
|
|
=head2 $app->inject_components |
3043
|
163
|
|
|
|
|
602
|
|
3044
|
|
|
|
|
|
|
Inject a list of components: |
3045
|
|
|
|
|
|
|
|
3046
|
|
|
|
|
|
|
MyApp->inject_components( |
3047
|
|
|
|
|
|
|
'Model::FooOne' => { |
3048
|
|
|
|
|
|
|
from_component => 'Common::Model::Foo', |
3049
|
6696
|
|
|
|
|
30879
|
roles => ['Role1', 'Role2'], |
3050
|
|
|
|
|
|
|
}, |
3051
|
|
|
|
|
|
|
'Model::FooTwo' => { |
3052
|
163
|
|
|
|
|
741
|
from_component => 'Common::Model::Foo', |
3053
|
6696
|
|
|
|
|
15078
|
roles => ['Role1', 'Role2'], |
3054
|
|
|
|
|
|
|
}); |
3055
|
|
|
|
|
|
|
|
3056
|
|
|
|
|
|
|
=cut |
3057
|
|
|
|
|
|
|
|
3058
|
|
|
|
|
|
|
my ($app, $name, $args) = @_; |
3059
|
|
|
|
|
|
|
die "Component $name exists" if |
3060
|
163
|
|
|
|
|
4015
|
$app->config->{inject_components}->{$name}; |
3061
|
|
|
|
|
|
|
$app->config->{inject_components}->{$name} = $args; |
3062
|
|
|
|
|
|
|
} |
3063
|
163
|
|
|
|
|
628
|
|
3064
|
|
|
|
|
|
|
my $app = shift; |
3065
|
6701
|
50
|
50
|
|
|
16806
|
while(@_) { |
3066
|
|
|
|
|
|
|
$app->inject_component(shift, shift); |
3067
|
|
|
|
|
|
|
} |
3068
|
|
|
|
|
|
|
} |
3069
|
|
|
|
|
|
|
|
3070
|
|
|
|
|
|
|
=head2 $c->locate_components( $setup_component_config ) |
3071
|
|
|
|
|
|
|
|
3072
|
|
|
|
|
|
|
This method is meant to provide a list of component modules that should be |
3073
|
|
|
|
|
|
|
setup for the application. By default, it will use L<Module::Pluggable>. |
3074
|
|
|
|
|
|
|
|
3075
|
|
|
|
|
|
|
Specify a C<setup_components> config option to pass additional options directly |
3076
|
163
|
|
|
163
|
1
|
730
|
to L<Module::Pluggable>. To add additional search paths, specify a key named |
3077
|
163
|
100
|
|
|
|
711
|
C<search_extra> as an array reference. Items in the array beginning with C<::> |
|
163
|
|
|
|
|
1010
|
|
3078
|
|
|
|
|
|
|
will have the application class name prepended to them. |
3079
|
163
|
|
|
|
|
833
|
|
3080
|
|
|
|
|
|
|
=cut |
3081
|
|
|
|
|
|
|
|
3082
|
5
|
|
|
|
|
17
|
my $class = shift; |
3083
|
|
|
|
|
|
|
my $config = shift; |
3084
|
|
|
|
|
|
|
|
3085
|
163
|
|
|
|
|
722
|
my @paths = qw( ::M ::Model ::V ::View ::C ::Controller ); |
|
5
|
|
|
|
|
15
|
|
3086
|
|
|
|
|
|
|
my $extra = $config->{ search_extra } || []; |
3087
|
|
|
|
|
|
|
|
3088
|
|
|
|
|
|
|
unshift @paths, @$extra; |
3089
|
|
|
|
|
|
|
|
3090
|
|
|
|
|
|
|
my @comps = map { sort { length($a) <=> length($b) } Module::Pluggable::Object->new( |
3091
|
|
|
|
|
|
|
search_path => [ map { s/^(?=::)/$class/; $_; } ($_) ], |
3092
|
|
|
|
|
|
|
%$config |
3093
|
|
|
|
|
|
|
)->plugins } @paths; |
3094
|
|
|
|
|
|
|
|
3095
|
|
|
|
|
|
|
return @comps; |
3096
|
5
|
|
|
5
|
1
|
12
|
} |
3097
|
5
|
50
|
|
|
|
20
|
|
3098
|
5
|
100
|
|
|
|
7
|
=head2 $c->expand_component_module( $component, $setup_component_config ) |
|
5
|
|
|
|
|
23
|
|
3099
|
5
|
100
|
|
|
|
25
|
|
3100
|
|
|
|
|
|
|
Components found by C<locate_components> will be passed to this method, which |
3101
|
|
|
|
|
|
|
is expected to return a list of component (package) names to be set up. |
3102
|
|
|
|
|
|
|
|
3103
|
|
|
|
|
|
|
=cut |
3104
|
|
|
|
|
|
|
|
3105
|
|
|
|
|
|
|
my ($class, $module) = @_; |
3106
|
|
|
|
|
|
|
return Devel::InnerPackage::list_packages( $module ); |
3107
|
|
|
|
|
|
|
} |
3108
|
|
|
|
|
|
|
|
3109
|
|
|
|
|
|
|
=head2 $app->delayed_setup_component |
3110
|
|
|
|
|
|
|
|
3111
|
|
|
|
|
|
|
Returns a coderef that points to a setup_component instance. Used |
3112
|
|
|
|
|
|
|
internally for when you want to delay setup until the first time |
3113
|
|
|
|
|
|
|
the component is called. |
3114
|
|
|
|
|
|
|
|
3115
|
|
|
|
|
|
|
=cut |
3116
|
|
|
|
|
|
|
|
3117
|
|
|
|
|
|
|
my($class, $component, @more) = @_; |
3118
|
|
|
|
|
|
|
return sub { |
3119
|
|
|
|
|
|
|
return my $instance = $class->setup_component($component, @more); |
3120
|
|
|
|
|
|
|
}; |
3121
|
|
|
|
|
|
|
} |
3122
|
|
|
|
|
|
|
|
3123
|
|
|
|
|
|
|
=head2 $c->setup_component |
3124
|
|
|
|
|
|
|
|
3125
|
|
|
|
|
|
|
=cut |
3126
|
|
|
|
|
|
|
|
3127
|
|
|
|
|
|
|
my( $class, $component ) = @_; |
3128
|
|
|
|
|
|
|
|
3129
|
|
|
|
|
|
|
unless ( $component->can( 'COMPONENT' ) ) { |
3130
|
|
|
|
|
|
|
return $component; |
3131
|
|
|
|
|
|
|
} |
3132
|
|
|
|
|
|
|
|
3133
|
|
|
|
|
|
|
my $config = $class->config_for($component); |
3134
|
|
|
|
|
|
|
# Stash catalyst_component_name in the config here, so that custom COMPONENT |
3135
|
|
|
|
|
|
|
# methods also pass it. local to avoid pointlessly shitting in config |
3136
|
|
|
|
|
|
|
# for the debug screen, as $component is already the key name. |
3137
|
|
|
|
|
|
|
local $config->{catalyst_component_name} = $component; |
3138
|
|
|
|
|
|
|
|
3139
|
|
|
|
|
|
|
my $instance = eval { |
3140
|
|
|
|
|
|
|
$component->COMPONENT( $class, $config ); |
3141
|
|
|
|
|
|
|
} || do { |
3142
|
|
|
|
|
|
|
my $error = $@; |
3143
|
|
|
|
|
|
|
chomp $error; |
3144
|
|
|
|
|
|
|
Catalyst::Exception->throw( |
3145
|
|
|
|
|
|
|
message => qq/Couldn't instantiate component "$component", "$error"/ |
3146
|
|
|
|
|
|
|
); |
3147
|
|
|
|
|
|
|
}; |
3148
|
|
|
|
|
|
|
|
3149
|
|
|
|
|
|
|
unless (blessed $instance) { |
3150
|
|
|
|
|
|
|
my $metaclass = Moose::Util::find_meta($component); |
3151
|
|
|
|
|
|
|
my $method_meta = $metaclass->find_method_by_name('COMPONENT'); |
3152
|
|
|
|
|
|
|
my $component_method_from = $method_meta->associated_metaclass->name; |
3153
|
2
|
|
|
2
|
1
|
5
|
my $value = defined($instance) ? $instance : 'undef'; |
3154
|
|
|
|
|
|
|
Catalyst::Exception->throw( |
3155
|
2
|
50
|
|
|
|
10
|
message => |
3156
|
2
|
|
|
|
|
7
|
qq/Couldn't instantiate component "$component", COMPONENT() method (from $component_method_from) didn't return an object-like value (value was $value)./ |
3157
|
|
|
|
|
|
|
); |
3158
|
|
|
|
|
|
|
} |
3159
|
|
|
|
|
|
|
|
3160
|
1
|
|
|
1
|
1
|
16
|
my @expanded_components = $instance->can('expand_modules') |
3161
|
1
|
|
|
|
|
4
|
? $instance->expand_modules( $component, $config ) |
3162
|
2
|
|
|
|
|
10
|
: $class->expand_component_module( $component, $config ); |
3163
|
|
|
|
|
|
|
for my $component (@expanded_components) { |
3164
|
|
|
|
|
|
|
next if $class->components->{ $component }; |
3165
|
|
|
|
|
|
|
$class->components->{ $component } = $class->setup_component($component); |
3166
|
|
|
|
|
|
|
} |
3167
|
|
|
|
|
|
|
|
3168
|
|
|
|
|
|
|
return $instance; |
3169
|
|
|
|
|
|
|
} |
3170
|
|
|
|
|
|
|
|
3171
|
|
|
|
|
|
|
=head2 $app->config_for( $component_name ) |
3172
|
|
|
|
|
|
|
|
3173
|
|
|
|
|
|
|
Return the application level configuration (which is not yet merged with any |
3174
|
|
|
|
|
|
|
local component configuration, via $component_class->config) for the named |
3175
|
|
|
|
|
|
|
component or component object. Example: |
3176
|
|
|
|
|
|
|
|
3177
|
|
|
|
|
|
|
MyApp->config( |
3178
|
|
|
|
|
|
|
'Model::Foo' => { a => 1, b => 2}, |
3179
|
163
|
|
|
163
|
1
|
603
|
); |
3180
|
163
|
|
|
|
|
397
|
|
3181
|
|
|
|
|
|
|
my $config = MyApp->config_for('MyApp::Model::Foo'); |
3182
|
163
|
|
|
|
|
773
|
|
3183
|
163
|
|
100
|
|
|
1350
|
In this case $config is the hashref C<< {a=>1, b=>2} >>. |
3184
|
|
|
|
|
|
|
|
3185
|
163
|
|
|
|
|
563
|
This is also handy for looking up configuration for a plugin, to make sure you follow |
3186
|
|
|
|
|
|
|
existing L<Catalyst> standards for where a plugin should put its configuration. |
3187
|
163
|
|
|
|
|
599
|
|
|
27794
|
|
|
|
|
1659240
|
|
3188
|
980
|
|
|
|
|
281633
|
=cut |
|
980
|
|
|
|
|
4489
|
|
|
980
|
|
|
|
|
6647
|
|
3189
|
|
|
|
|
|
|
|
3190
|
|
|
|
|
|
|
my ($class, $component_name) = @_; |
3191
|
|
|
|
|
|
|
my $component_suffix = Catalyst::Utils::class2classsuffix($component_name); |
3192
|
163
|
|
|
|
|
60699
|
my $config = $class->config->{ $component_suffix } || {}; |
3193
|
|
|
|
|
|
|
|
3194
|
|
|
|
|
|
|
return $config; |
3195
|
|
|
|
|
|
|
} |
3196
|
|
|
|
|
|
|
|
3197
|
|
|
|
|
|
|
=head2 $c->setup_dispatcher |
3198
|
|
|
|
|
|
|
|
3199
|
|
|
|
|
|
|
Sets up dispatcher. |
3200
|
|
|
|
|
|
|
|
3201
|
|
|
|
|
|
|
=cut |
3202
|
|
|
|
|
|
|
|
3203
|
0
|
|
|
0
|
1
|
0
|
my ( $class, $dispatcher ) = @_; |
3204
|
0
|
|
|
|
|
0
|
|
3205
|
|
|
|
|
|
|
if ($dispatcher) { |
3206
|
|
|
|
|
|
|
$dispatcher = 'Catalyst::Dispatcher::' . $dispatcher; |
3207
|
|
|
|
|
|
|
} |
3208
|
|
|
|
|
|
|
|
3209
|
|
|
|
|
|
|
if ( my $env = Catalyst::Utils::env_value( $class, 'DISPATCHER' ) ) { |
3210
|
|
|
|
|
|
|
$dispatcher = 'Catalyst::Dispatcher::' . $env; |
3211
|
|
|
|
|
|
|
} |
3212
|
|
|
|
|
|
|
|
3213
|
|
|
|
|
|
|
unless ($dispatcher) { |
3214
|
|
|
|
|
|
|
$dispatcher = $class->dispatcher_class; |
3215
|
|
|
|
|
|
|
} |
3216
|
6707
|
|
|
6707
|
1
|
13505
|
|
3217
|
|
|
|
|
|
|
load_class($dispatcher); |
3218
|
6716
|
|
|
6716
|
|
16805
|
|
3219
|
6707
|
|
|
|
|
31186
|
# dispatcher instance |
3220
|
|
|
|
|
|
|
$class->dispatcher( $dispatcher->new ); |
3221
|
|
|
|
|
|
|
} |
3222
|
|
|
|
|
|
|
|
3223
|
|
|
|
|
|
|
=head2 $c->setup_engine |
3224
|
|
|
|
|
|
|
|
3225
|
|
|
|
|
|
|
Sets up engine. |
3226
|
|
|
|
|
|
|
|
3227
|
7191
|
|
|
7191
|
1
|
14098
|
=cut |
3228
|
|
|
|
|
|
|
|
3229
|
7191
|
100
|
|
|
|
110509
|
my ($class, $requested_engine) = @_; |
3230
|
238
|
|
|
|
|
1113
|
|
3231
|
|
|
|
|
|
|
if (!$class->engine_loader || $requested_engine) { |
3232
|
|
|
|
|
|
|
$class->engine_loader( |
3233
|
6953
|
|
|
|
|
19806
|
Catalyst::EngineLoader->new({ |
3234
|
|
|
|
|
|
|
application_name => $class, |
3235
|
|
|
|
|
|
|
(defined $requested_engine |
3236
|
|
|
|
|
|
|
? (catalyst_engine_class => $requested_engine) : ()), |
3237
|
6953
|
|
|
|
|
18779
|
}), |
3238
|
|
|
|
|
|
|
); |
3239
|
|
|
|
|
|
|
} |
3240
|
|
|
|
|
|
|
|
3241
|
6953
|
|
33
|
|
|
12097
|
$class->engine_loader->catalyst_engine_class; |
3242
|
|
|
|
|
|
|
} |
3243
|
|
|
|
|
|
|
|
3244
|
|
|
|
|
|
|
my ($class, $requested_engine) = @_; |
3245
|
|
|
|
|
|
|
|
3246
|
|
|
|
|
|
|
my $engine = do { |
3247
|
|
|
|
|
|
|
my $loader = $class->engine_loader; |
3248
|
|
|
|
|
|
|
|
3249
|
6953
|
50
|
|
|
|
704282
|
if (!$loader || $requested_engine) { |
3250
|
0
|
|
|
|
|
0
|
$loader = Catalyst::EngineLoader->new({ |
3251
|
0
|
|
|
|
|
0
|
application_name => $class, |
3252
|
0
|
|
|
|
|
0
|
(defined $requested_engine |
3253
|
0
|
0
|
|
|
|
0
|
? (requested_engine => $requested_engine) : ()), |
3254
|
0
|
|
|
|
|
0
|
}), |
3255
|
|
|
|
|
|
|
|
3256
|
|
|
|
|
|
|
$class->engine_loader($loader); |
3257
|
|
|
|
|
|
|
} |
3258
|
|
|
|
|
|
|
|
3259
|
|
|
|
|
|
|
$loader->catalyst_engine_class; |
3260
|
6953
|
50
|
|
|
|
57913
|
}; |
3261
|
|
|
|
|
|
|
|
3262
|
|
|
|
|
|
|
# Don't really setup_engine -- see _setup_psgi_app for explanation. |
3263
|
6953
|
|
|
|
|
551470
|
return if $class->loading_psgi_file; |
3264
|
6955
|
100
|
|
|
|
15591
|
|
3265
|
475
|
|
|
|
|
2134
|
load_class($engine); |
3266
|
|
|
|
|
|
|
|
3267
|
|
|
|
|
|
|
if ($ENV{MOD_PERL}) { |
3268
|
6953
|
|
|
|
|
37888
|
my $apache = $class->engine_loader->auto; |
3269
|
|
|
|
|
|
|
|
3270
|
|
|
|
|
|
|
my $meta = find_meta($class); |
3271
|
|
|
|
|
|
|
my $was_immutable = $meta->is_immutable; |
3272
|
|
|
|
|
|
|
my %immutable_options = $meta->immutable_options; |
3273
|
|
|
|
|
|
|
$meta->make_mutable if $was_immutable; |
3274
|
|
|
|
|
|
|
|
3275
|
|
|
|
|
|
|
$meta->add_method(handler => sub { |
3276
|
|
|
|
|
|
|
my $r = shift; |
3277
|
|
|
|
|
|
|
my $psgi_app = $class->_finalized_psgi_app; |
3278
|
|
|
|
|
|
|
$apache->call_app($r, $psgi_app); |
3279
|
|
|
|
|
|
|
}); |
3280
|
|
|
|
|
|
|
|
3281
|
|
|
|
|
|
|
$meta->make_immutable(%immutable_options) if $was_immutable; |
3282
|
|
|
|
|
|
|
} |
3283
|
|
|
|
|
|
|
|
3284
|
|
|
|
|
|
|
$class->engine( $engine->new ); |
3285
|
|
|
|
|
|
|
|
3286
|
|
|
|
|
|
|
return; |
3287
|
|
|
|
|
|
|
} |
3288
|
|
|
|
|
|
|
|
3289
|
|
|
|
|
|
|
## This exists just to supply a prebuild psgi app for mod_perl and for the |
3290
|
|
|
|
|
|
|
## build in server support (back compat support for pre psgi port behavior). |
3291
|
6953
|
|
|
6953
|
1
|
12758
|
## This is so that we don't build a new psgi app for each request when using |
3292
|
6953
|
|
|
|
|
19368
|
## the mod_perl handler or the built in servers (http and fcgi, etc). |
3293
|
6953
|
|
100
|
|
|
23532
|
|
3294
|
|
|
|
|
|
|
my ($app) = @_; |
3295
|
6953
|
|
|
|
|
14649
|
|
3296
|
|
|
|
|
|
|
unless ($app->_psgi_app) { |
3297
|
|
|
|
|
|
|
my $psgi_app = $app->_setup_psgi_app; |
3298
|
|
|
|
|
|
|
$app->_psgi_app($psgi_app); |
3299
|
|
|
|
|
|
|
} |
3300
|
|
|
|
|
|
|
|
3301
|
|
|
|
|
|
|
return $app->_psgi_app; |
3302
|
|
|
|
|
|
|
} |
3303
|
|
|
|
|
|
|
|
3304
|
|
|
|
|
|
|
## Look for a psgi file like 'myapp_web.psgi' (if the app is MyApp::Web) in the |
3305
|
163
|
|
|
163
|
1
|
8254
|
## home directory and load that and return it (just assume it is doing the |
3306
|
|
|
|
|
|
|
## right thing :) ). If that does not exist, call $app->psgi_app, wrap that |
3307
|
163
|
50
|
|
|
|
792
|
## in default_middleware and return it ( this is for backward compatibility |
3308
|
0
|
|
|
|
|
0
|
## with pre psgi port behavior ). |
3309
|
|
|
|
|
|
|
|
3310
|
|
|
|
|
|
|
my ($app) = @_; |
3311
|
163
|
50
|
|
|
|
1004
|
|
3312
|
0
|
|
|
|
|
0
|
for my $home (Path::Class::Dir->new($app->config->{home})) { |
3313
|
|
|
|
|
|
|
my $psgi_file = $home->file( |
3314
|
|
|
|
|
|
|
Catalyst::Utils::appprefix($app) . '.psgi', |
3315
|
163
|
50
|
|
|
|
778
|
); |
3316
|
163
|
|
|
|
|
1546
|
|
3317
|
|
|
|
|
|
|
next unless -e $psgi_file; |
3318
|
|
|
|
|
|
|
|
3319
|
163
|
|
|
|
|
1188
|
# If $psgi_file calls ->setup_engine, it's doing so to load |
3320
|
|
|
|
|
|
|
# Catalyst::Engine::PSGI. But if it does that, we're only going to |
3321
|
|
|
|
|
|
|
# throw away the loaded PSGI-app and load the 5.9 Catalyst::Engine |
3322
|
163
|
|
|
|
|
11487
|
# anyway. So set a flag (ick) that tells setup_engine not to populate |
3323
|
|
|
|
|
|
|
# $c->engine or do any other things we might regret. |
3324
|
|
|
|
|
|
|
|
3325
|
|
|
|
|
|
|
$app->loading_psgi_file(1); |
3326
|
|
|
|
|
|
|
my $psgi_app = Plack::Util::load_psgi($psgi_file); |
3327
|
|
|
|
|
|
|
$app->loading_psgi_file(0); |
3328
|
|
|
|
|
|
|
|
3329
|
|
|
|
|
|
|
return $psgi_app |
3330
|
|
|
|
|
|
|
unless $app->engine_loader->needs_psgi_engine_compat_hack; |
3331
|
|
|
|
|
|
|
|
3332
|
0
|
|
|
0
|
1
|
0
|
warn <<"EOW"; |
3333
|
|
|
|
|
|
|
Found a legacy Catalyst::Engine::PSGI .psgi file at ${psgi_file}. |
3334
|
0
|
0
|
0
|
|
|
0
|
|
3335
|
0
|
0
|
|
|
|
0
|
Its content has been ignored. Please consult the Catalyst::Upgrading |
3336
|
|
|
|
|
|
|
documentation on how to upgrade from Catalyst::Engine::PSGI. |
3337
|
|
|
|
|
|
|
EOW |
3338
|
|
|
|
|
|
|
} |
3339
|
|
|
|
|
|
|
|
3340
|
|
|
|
|
|
|
return $app->apply_default_middlewares($app->psgi_app); |
3341
|
|
|
|
|
|
|
} |
3342
|
|
|
|
|
|
|
|
3343
|
|
|
|
|
|
|
=head2 $c->apply_default_middlewares |
3344
|
0
|
|
|
|
|
0
|
|
3345
|
|
|
|
|
|
|
Adds the following L<Plack> middlewares to your application, since they are |
3346
|
|
|
|
|
|
|
useful and commonly needed: |
3347
|
|
|
|
|
|
|
|
3348
|
163
|
|
|
163
|
1
|
664
|
L<Plack::Middleware::LighttpdScriptNameFix> (if you are using Lighttpd), |
3349
|
|
|
|
|
|
|
L<Plack::Middleware::IIS6ScriptNameFix> (always applied since this middleware |
3350
|
163
|
|
|
|
|
454
|
is smart enough to conditionally apply itself). |
3351
|
163
|
|
|
|
|
1488
|
|
3352
|
|
|
|
|
|
|
We will also automatically add L<Plack::Middleware::ReverseProxy> if we notice |
3353
|
163
|
50
|
33
|
|
|
1082
|
that your HTTP $env variable C<REMOTE_ADDR> is '127.0.0.1'. This is usually |
3354
|
163
|
50
|
|
|
|
7562
|
an indication that your server is running behind a proxy frontend. However in |
3355
|
|
|
|
|
|
|
2014 this is often not the case. We preserve this code for backwards compatibility |
3356
|
|
|
|
|
|
|
however I B<highly> recommend that if you are running the server behind a front |
3357
|
|
|
|
|
|
|
end proxy that you clearly indicate so with the C<using_frontend_proxy> configuration |
3358
|
|
|
|
|
|
|
setting to true for your environment configurations that run behind a proxy. This |
3359
|
|
|
|
|
|
|
way if you change your front end proxy address someday your code would inexplicably |
3360
|
|
|
|
|
|
|
stop working as expected. |
3361
|
|
|
|
|
|
|
|
3362
|
|
|
|
|
|
|
Additionally if we detect we are using Nginx, we add a bit of custom middleware |
3363
|
163
|
|
|
|
|
7201
|
to solve some problems with the way that server handles $ENV{PATH_INFO} and |
3364
|
|
|
|
|
|
|
$ENV{SCRIPT_NAME}. |
3365
|
|
|
|
|
|
|
|
3366
|
|
|
|
|
|
|
Please B<NOTE> that if you do use C<using_frontend_proxy> the middleware is now |
3367
|
163
|
50
|
|
|
|
3802
|
adding via C<registered_middleware> rather than this method. |
3368
|
|
|
|
|
|
|
|
3369
|
163
|
|
|
|
|
1697
|
If you are using Lighttpd or IIS6 you may wish to apply these middlewares. In |
3370
|
|
|
|
|
|
|
general this is no longer a common case but we have this here for backward |
3371
|
163
|
50
|
|
|
|
5924
|
compatibility. |
3372
|
0
|
|
|
|
|
0
|
|
3373
|
|
|
|
|
|
|
=cut |
3374
|
0
|
|
|
|
|
0
|
|
3375
|
0
|
|
|
|
|
0
|
|
3376
|
0
|
|
|
|
|
0
|
my ($app, $psgi_app) = @_; |
3377
|
0
|
0
|
|
|
|
0
|
|
3378
|
|
|
|
|
|
|
# Don't add this conditional IF we are explicitly saying we want the |
3379
|
|
|
|
|
|
|
# frontend proxy support. We don't need it here since if that is the |
3380
|
0
|
|
|
0
|
|
0
|
# case it will be always loaded in the default_middleware. |
3381
|
0
|
|
|
|
|
0
|
|
3382
|
0
|
|
|
|
|
0
|
unless($app->config->{using_frontend_proxy}) { |
3383
|
0
|
|
|
|
|
0
|
$psgi_app = Plack::Middleware::Conditional->wrap( |
3384
|
|
|
|
|
|
|
$psgi_app, |
3385
|
0
|
0
|
|
|
|
0
|
builder => sub { Plack::Middleware::ReverseProxy->wrap($_[0]) }, |
3386
|
|
|
|
|
|
|
condition => sub { |
3387
|
|
|
|
|
|
|
my ($env) = @_; |
3388
|
163
|
|
|
|
|
5443
|
return if $app->config->{ignore_frontend_proxy}; |
3389
|
|
|
|
|
|
|
return $env->{REMOTE_ADDR} && $env->{REMOTE_ADDR} eq '127.0.0.1'; |
3390
|
163
|
|
|
|
|
529
|
}, |
3391
|
|
|
|
|
|
|
); |
3392
|
|
|
|
|
|
|
} |
3393
|
|
|
|
|
|
|
|
3394
|
|
|
|
|
|
|
# If we're running under Lighttpd, swap PATH_INFO and SCRIPT_NAME |
3395
|
|
|
|
|
|
|
# http://lists.scsys.co.uk/pipermail/catalyst/2006-June/008361.html |
3396
|
|
|
|
|
|
|
$psgi_app = Plack::Middleware::Conditional->wrap( |
3397
|
|
|
|
|
|
|
$psgi_app, |
3398
|
|
|
|
|
|
|
builder => sub { Plack::Middleware::LighttpdScriptNameFix->wrap($_[0]) }, |
3399
|
910
|
|
|
910
|
|
3017
|
condition => sub { |
3400
|
|
|
|
|
|
|
my ($env) = @_; |
3401
|
910
|
100
|
|
|
|
5093
|
return unless $env->{SERVER_SOFTWARE} && $env->{SERVER_SOFTWARE} =~ m!lighttpd[-/]1\.(\d+\.\d+)!; |
3402
|
122
|
|
|
|
|
1130
|
return unless $1 < 4.23; |
3403
|
122
|
|
|
|
|
680
|
1; |
3404
|
|
|
|
|
|
|
}, |
3405
|
|
|
|
|
|
|
); |
3406
|
910
|
|
|
|
|
3413
|
|
3407
|
|
|
|
|
|
|
# we're applying this unconditionally as the middleware itself already makes |
3408
|
|
|
|
|
|
|
# sure it doesn't fuck things up if it's not running under one of the right |
3409
|
|
|
|
|
|
|
# IIS versions |
3410
|
|
|
|
|
|
|
$psgi_app = Plack::Middleware::IIS6ScriptNameFix->wrap($psgi_app); |
3411
|
|
|
|
|
|
|
|
3412
|
|
|
|
|
|
|
# And another IIS issue, this time with IIS7. |
3413
|
|
|
|
|
|
|
$psgi_app = Plack::Middleware::Conditional->wrap( |
3414
|
|
|
|
|
|
|
$psgi_app, |
3415
|
|
|
|
|
|
|
builder => sub { Plack::Middleware::IIS7KeepAliveFix->wrap($_[0]) }, |
3416
|
122
|
|
|
122
|
|
531
|
condition => sub { |
3417
|
|
|
|
|
|
|
my ($env) = @_; |
3418
|
122
|
|
|
|
|
1113
|
return $env->{SERVER_SOFTWARE} && $env->{SERVER_SOFTWARE} =~ m!IIS/7\.[0-9]!; |
3419
|
90
|
|
|
|
|
13048
|
}, |
3420
|
|
|
|
|
|
|
); |
3421
|
|
|
|
|
|
|
|
3422
|
|
|
|
|
|
|
return $psgi_app; |
3423
|
90
|
100
|
|
|
|
12775
|
} |
3424
|
|
|
|
|
|
|
|
3425
|
|
|
|
|
|
|
=head2 App->psgi_app |
3426
|
|
|
|
|
|
|
|
3427
|
|
|
|
|
|
|
=head2 App->to_app |
3428
|
|
|
|
|
|
|
|
3429
|
|
|
|
|
|
|
Returns a PSGI application code reference for the catalyst application |
3430
|
|
|
|
|
|
|
C<$c>. This is the bare application created without the C<apply_default_middlewares> |
3431
|
2
|
|
|
|
|
204
|
method called. We do however apply C<registered_middleware> since those are |
3432
|
2
|
|
|
|
|
34
|
integral to how L<Catalyst> functions. Also, unlike starting your application |
3433
|
2
|
|
|
|
|
81
|
with a generated server script (via L<Catalyst::Devel> and C<catalyst.pl>) we do |
3434
|
|
|
|
|
|
|
not attempt to return a valid L<PSGI> application using any existing C<${myapp}.psgi> |
3435
|
2
|
50
|
|
|
|
35
|
scripts in your $HOME directory. |
3436
|
|
|
|
|
|
|
|
3437
|
|
|
|
|
|
|
B<NOTE> C<apply_default_middlewares> was originally created when the first PSGI |
3438
|
0
|
|
|
|
|
0
|
port was done for v5.90000. These are middlewares that are added to achieve |
3439
|
|
|
|
|
|
|
backward compatibility with older applications. If you start your application |
3440
|
|
|
|
|
|
|
using one of the supplied server scripts (generated with L<Catalyst::Devel> and |
3441
|
|
|
|
|
|
|
the project skeleton script C<catalyst.pl>) we apply C<apply_default_middlewares> |
3442
|
|
|
|
|
|
|
automatically. This was done so that pre and post PSGI port applications would |
3443
|
|
|
|
|
|
|
work the same way. |
3444
|
|
|
|
|
|
|
|
3445
|
|
|
|
|
|
|
This is what you want to be using to retrieve the PSGI application code |
3446
|
120
|
|
|
|
|
9604
|
reference of your Catalyst application for use in a custom F<.psgi> or in your |
3447
|
|
|
|
|
|
|
own created server modules. |
3448
|
|
|
|
|
|
|
|
3449
|
|
|
|
|
|
|
=cut |
3450
|
|
|
|
|
|
|
|
3451
|
|
|
|
|
|
|
*to_app = \&psgi_app; |
3452
|
|
|
|
|
|
|
|
3453
|
|
|
|
|
|
|
my ($app) = @_; |
3454
|
|
|
|
|
|
|
my $psgi = $app->engine->build_psgi_app($app); |
3455
|
|
|
|
|
|
|
return $app->Catalyst::Utils::apply_registered_middleware($psgi); |
3456
|
|
|
|
|
|
|
} |
3457
|
|
|
|
|
|
|
|
3458
|
|
|
|
|
|
|
=head2 $c->setup_home |
3459
|
|
|
|
|
|
|
|
3460
|
|
|
|
|
|
|
Sets up the home directory. |
3461
|
|
|
|
|
|
|
|
3462
|
|
|
|
|
|
|
=cut |
3463
|
|
|
|
|
|
|
|
3464
|
|
|
|
|
|
|
my ( $class, $home ) = @_; |
3465
|
|
|
|
|
|
|
|
3466
|
|
|
|
|
|
|
if ( my $env = Catalyst::Utils::env_value( $class, 'HOME' ) ) { |
3467
|
|
|
|
|
|
|
$home = $env; |
3468
|
|
|
|
|
|
|
} |
3469
|
|
|
|
|
|
|
|
3470
|
|
|
|
|
|
|
$home ||= Catalyst::Utils::home($class); |
3471
|
|
|
|
|
|
|
|
3472
|
|
|
|
|
|
|
if ($home) { |
3473
|
|
|
|
|
|
|
#I remember recently being scolded for assigning config values like this |
3474
|
|
|
|
|
|
|
$class->config->{home} ||= $home; |
3475
|
|
|
|
|
|
|
$class->config->{root} ||= Path::Class::Dir->new($home)->subdir('root'); |
3476
|
|
|
|
|
|
|
} |
3477
|
|
|
|
|
|
|
} |
3478
|
|
|
|
|
|
|
|
3479
|
|
|
|
|
|
|
=head2 $c->setup_encoding |
3480
|
|
|
|
|
|
|
|
3481
|
|
|
|
|
|
|
Sets up the input/output encoding. See L<ENCODING> |
3482
|
|
|
|
|
|
|
|
3483
|
122
|
|
|
122
|
1
|
846
|
=cut |
3484
|
|
|
|
|
|
|
|
3485
|
|
|
|
|
|
|
my $c = shift; |
3486
|
|
|
|
|
|
|
if( exists($c->config->{encoding}) && !defined($c->config->{encoding}) ) { |
3487
|
|
|
|
|
|
|
# Ok, so the user has explicitly said "I don't want encoding..." |
3488
|
|
|
|
|
|
|
return; |
3489
|
122
|
50
|
|
|
|
610
|
} else { |
3490
|
|
|
|
|
|
|
my $enc = defined($c->config->{encoding}) ? |
3491
|
|
|
|
|
|
|
delete $c->config->{encoding} : 'UTF-8'; # not sure why we delete it... (JNAP) |
3492
|
122
|
|
|
122
|
|
12131
|
$c->encoding($enc); |
3493
|
|
|
|
|
|
|
} |
3494
|
910
|
|
|
910
|
|
14062
|
} |
3495
|
910
|
100
|
|
|
|
6266
|
|
3496
|
909
|
|
66
|
|
|
5881
|
=head2 handle_unicode_encoding_exception |
3497
|
|
|
|
|
|
|
|
3498
|
122
|
|
|
|
|
2044
|
Hook to let you customize how encoding errors are handled. By default |
3499
|
|
|
|
|
|
|
we just throw an exception and the default error page will pick it up. |
3500
|
|
|
|
|
|
|
Receives a hashref of debug information. Example of call (from the |
3501
|
|
|
|
|
|
|
Catalyst internals): |
3502
|
|
|
|
|
|
|
|
3503
|
|
|
|
|
|
|
my $decoded_after_fail = $c->handle_unicode_encoding_exception({ |
3504
|
|
|
|
|
|
|
param_value => $value, |
3505
|
122
|
|
|
122
|
|
4759
|
error_msg => $_, |
3506
|
|
|
|
|
|
|
encoding_step => 'params', |
3507
|
910
|
|
|
910
|
|
38592
|
}); |
3508
|
910
|
100
|
100
|
|
|
4745
|
|
3509
|
1
|
50
|
|
|
|
6
|
The calling code expects to receive a decoded string or an exception. |
3510
|
1
|
|
|
|
|
3
|
|
3511
|
|
|
|
|
|
|
You can override this for custom handling of unicode errors. By |
3512
|
122
|
|
|
|
|
6766
|
default we just die. If you want a custom response here, one approach |
3513
|
|
|
|
|
|
|
is to throw an HTTP style exception, instead of returning a decoded |
3514
|
|
|
|
|
|
|
string or throwing a generic exception. |
3515
|
|
|
|
|
|
|
|
3516
|
|
|
|
|
|
|
sub handle_unicode_encoding_exception { |
3517
|
122
|
|
|
|
|
12177
|
my ($c, $params) = @_; |
3518
|
|
|
|
|
|
|
HTTP::Exception::BAD_REQUEST->throw(status_message=>$params->{error_msg}); |
3519
|
|
|
|
|
|
|
} |
3520
|
|
|
|
|
|
|
|
3521
|
|
|
|
|
|
|
Alternatively you can 'catch' the error, stash it and write handling code later |
3522
|
122
|
|
|
122
|
|
4666
|
in your application: |
3523
|
|
|
|
|
|
|
|
3524
|
910
|
|
|
910
|
|
18872
|
sub handle_unicode_encoding_exception { |
3525
|
910
|
|
66
|
|
|
4484
|
my ($c, $params) = @_; |
3526
|
|
|
|
|
|
|
$c->stash(BAD_UNICODE_DATA=>$params); |
3527
|
122
|
|
|
|
|
4950
|
# return a dummy string. |
3528
|
|
|
|
|
|
|
return 1; |
3529
|
122
|
|
|
|
|
4753
|
} |
3530
|
|
|
|
|
|
|
|
3531
|
|
|
|
|
|
|
<B>NOTE:</b> Please keep in mind that once an error like this occurs, |
3532
|
|
|
|
|
|
|
the request setup is still ongoing, which means the state of C<$c> and |
3533
|
|
|
|
|
|
|
related context parts like the request and response may not be setup |
3534
|
|
|
|
|
|
|
up correctly (since we haven't finished the setup yet). If you throw |
3535
|
|
|
|
|
|
|
an exception the setup is aborted. |
3536
|
|
|
|
|
|
|
|
3537
|
|
|
|
|
|
|
=cut |
3538
|
|
|
|
|
|
|
|
3539
|
|
|
|
|
|
|
my ( $self, $exception_ctx ) = @_; |
3540
|
|
|
|
|
|
|
die $exception_ctx->{error_msg}; |
3541
|
|
|
|
|
|
|
} |
3542
|
|
|
|
|
|
|
|
3543
|
|
|
|
|
|
|
# Some unicode helpers cargo culted from the old plugin. These could likely |
3544
|
|
|
|
|
|
|
# be neater. |
3545
|
|
|
|
|
|
|
|
3546
|
|
|
|
|
|
|
my ( $self, $value ) = @_; |
3547
|
|
|
|
|
|
|
|
3548
|
|
|
|
|
|
|
return unless defined $value; |
3549
|
|
|
|
|
|
|
|
3550
|
|
|
|
|
|
|
## I think this mess is to support the old nested |
3551
|
|
|
|
|
|
|
if ( ref $value eq 'ARRAY' ) { |
3552
|
|
|
|
|
|
|
foreach ( @$value ) { |
3553
|
|
|
|
|
|
|
$_ = $self->_handle_unicode_decoding($_); |
3554
|
|
|
|
|
|
|
} |
3555
|
|
|
|
|
|
|
return $value; |
3556
|
|
|
|
|
|
|
} |
3557
|
|
|
|
|
|
|
elsif ( ref $value eq 'HASH' ) { |
3558
|
|
|
|
|
|
|
foreach (keys %$value) { |
3559
|
|
|
|
|
|
|
my $encoded_key = $self->_handle_param_unicode_decoding($_); |
3560
|
|
|
|
|
|
|
$value->{$encoded_key} = $self->_handle_unicode_decoding($value->{$_}); |
3561
|
134
|
|
|
134
|
1
|
5169
|
|
3562
|
134
|
|
|
|
|
1056
|
# If the key was encoded we now have two (the original and current so |
3563
|
134
|
|
|
|
|
1276
|
# delete the original. |
3564
|
|
|
|
|
|
|
delete $value->{$_} if $_ ne $encoded_key; |
3565
|
|
|
|
|
|
|
} |
3566
|
|
|
|
|
|
|
return $value; |
3567
|
|
|
|
|
|
|
} |
3568
|
|
|
|
|
|
|
else { |
3569
|
|
|
|
|
|
|
return $self->_handle_param_unicode_decoding($value); |
3570
|
|
|
|
|
|
|
} |
3571
|
|
|
|
|
|
|
} |
3572
|
|
|
|
|
|
|
|
3573
|
321
|
|
|
321
|
1
|
1085
|
my ( $self, $value, $check ) = @_; |
3574
|
|
|
|
|
|
|
return unless defined $value; # not in love with just ignoring undefs - jnap |
3575
|
321
|
100
|
|
|
|
3143
|
return $value if blessed($value); #don't decode when the value is an object. |
3576
|
2
|
|
|
|
|
3
|
|
3577
|
|
|
|
|
|
|
my $enc = $self->encoding; |
3578
|
|
|
|
|
|
|
|
3579
|
321
|
|
100
|
|
|
2083
|
return $value unless $enc; # don't decode if no encoding is specified |
3580
|
|
|
|
|
|
|
|
3581
|
321
|
100
|
|
|
|
37072
|
$check ||= $self->_encode_check; |
3582
|
|
|
|
|
|
|
return try { |
3583
|
219
|
|
66
|
|
|
1353
|
$enc->decode( $value, $check); |
3584
|
219
|
|
66
|
|
|
854
|
} |
3585
|
|
|
|
|
|
|
catch { |
3586
|
|
|
|
|
|
|
return $self->handle_unicode_encoding_exception({ |
3587
|
|
|
|
|
|
|
param_value => $value, |
3588
|
|
|
|
|
|
|
error_msg => $_, |
3589
|
|
|
|
|
|
|
encoding_step => 'params', |
3590
|
|
|
|
|
|
|
}); |
3591
|
|
|
|
|
|
|
}; |
3592
|
|
|
|
|
|
|
} |
3593
|
|
|
|
|
|
|
|
3594
|
|
|
|
|
|
|
=head2 $c->setup_log |
3595
|
163
|
|
|
163
|
1
|
2672
|
|
3596
|
163
|
100
|
100
|
|
|
3404
|
Sets up log by instantiating a L<Catalyst::Log|Catalyst::Log> object and |
3597
|
|
|
|
|
|
|
passing it to C<log()>. Pass in a comma-delimited list of levels to set the |
3598
|
1
|
|
|
|
|
3
|
log to. |
3599
|
|
|
|
|
|
|
|
3600
|
|
|
|
|
|
|
This method also installs a C<debug> method that returns a true value into the |
3601
|
162
|
100
|
|
|
|
811
|
catalyst subclass if the "debug" level is passed in the comma-delimited list, |
3602
|
162
|
|
|
|
|
1661
|
or if the C<$CATALYST_DEBUG> environment variable is set to a true value. |
3603
|
|
|
|
|
|
|
|
3604
|
|
|
|
|
|
|
Note that if the log has already been setup, by either a previous call to |
3605
|
|
|
|
|
|
|
C<setup_log> or by a call such as C<< __PACKAGE__->log( MyLogger->new ) >>, |
3606
|
|
|
|
|
|
|
that this method won't actually set up the log object. |
3607
|
|
|
|
|
|
|
|
3608
|
|
|
|
|
|
|
=cut |
3609
|
|
|
|
|
|
|
|
3610
|
|
|
|
|
|
|
my ( $class, $levels ) = @_; |
3611
|
|
|
|
|
|
|
|
3612
|
|
|
|
|
|
|
$levels ||= ''; |
3613
|
|
|
|
|
|
|
$levels =~ s/^\s+//; |
3614
|
|
|
|
|
|
|
$levels =~ s/\s+$//; |
3615
|
|
|
|
|
|
|
my %levels = map { $_ => 1 } split /\s*,\s*/, $levels; |
3616
|
|
|
|
|
|
|
|
3617
|
|
|
|
|
|
|
my $env_debug = Catalyst::Utils::env_value( $class, 'DEBUG' ); |
3618
|
|
|
|
|
|
|
if ( defined $env_debug ) { |
3619
|
|
|
|
|
|
|
$levels{debug} = 1 if $env_debug; # Ugly! |
3620
|
|
|
|
|
|
|
delete($levels{debug}) unless $env_debug; |
3621
|
|
|
|
|
|
|
} |
3622
|
|
|
|
|
|
|
|
3623
|
|
|
|
|
|
|
unless ( $class->log ) { |
3624
|
|
|
|
|
|
|
$class->log( Catalyst::Log->new(keys %levels) ); |
3625
|
|
|
|
|
|
|
} |
3626
|
|
|
|
|
|
|
|
3627
|
|
|
|
|
|
|
if ( $levels{debug} ) { |
3628
|
|
|
|
|
|
|
Class::MOP::get_metaclass_by_name($class)->add_method('debug' => sub { 1 }); |
3629
|
|
|
|
|
|
|
$class->log->debug('Debug messages enabled'); |
3630
|
|
|
|
|
|
|
} |
3631
|
|
|
|
|
|
|
} |
3632
|
|
|
|
|
|
|
|
3633
|
|
|
|
|
|
|
=head2 $c->setup_plugins |
3634
|
|
|
|
|
|
|
|
3635
|
|
|
|
|
|
|
Sets up plugins. |
3636
|
|
|
|
|
|
|
|
3637
|
|
|
|
|
|
|
=cut |
3638
|
|
|
|
|
|
|
|
3639
|
|
|
|
|
|
|
=head2 $c->setup_stats |
3640
|
|
|
|
|
|
|
|
3641
|
|
|
|
|
|
|
Sets up timing statistics class. |
3642
|
|
|
|
|
|
|
|
3643
|
|
|
|
|
|
|
=cut |
3644
|
|
|
|
|
|
|
|
3645
|
|
|
|
|
|
|
my ( $class, $stats ) = @_; |
3646
|
|
|
|
|
|
|
|
3647
|
|
|
|
|
|
|
Catalyst::Utils::ensure_class_loaded($class->stats_class); |
3648
|
|
|
|
|
|
|
|
3649
|
|
|
|
|
|
|
my $env = Catalyst::Utils::env_value( $class, 'STATS' ); |
3650
|
3
|
|
|
3
|
1
|
8
|
if ( defined($env) ? $env : ($stats || $class->debug ) ) { |
3651
|
3
|
|
|
|
|
22
|
Class::MOP::get_metaclass_by_name($class)->add_method('use_stats' => sub { 1 }); |
3652
|
|
|
|
|
|
|
$class->log->debug('Statistics enabled'); |
3653
|
|
|
|
|
|
|
} |
3654
|
|
|
|
|
|
|
} |
3655
|
|
|
|
|
|
|
|
3656
|
|
|
|
|
|
|
|
3657
|
|
|
|
|
|
|
=head2 $c->registered_plugins |
3658
|
120
|
|
|
120
|
|
288
|
|
3659
|
|
|
|
|
|
|
Returns a sorted list of the plugins which have either been stated in the |
3660
|
120
|
50
|
|
|
|
294
|
import list. |
3661
|
|
|
|
|
|
|
|
3662
|
|
|
|
|
|
|
If passed a given plugin name, it will report a boolean value indicating |
3663
|
120
|
100
|
|
|
|
392
|
whether or not that plugin is loaded. A fully qualified name is required if |
|
|
100
|
|
|
|
|
|
3664
|
3
|
|
|
|
|
15
|
the plugin name does not begin with C<Catalyst::Plugin::>. |
3665
|
12
|
|
|
|
|
168
|
|
3666
|
|
|
|
|
|
|
if ($c->registered_plugins('Some::Plugin')) { |
3667
|
3
|
|
|
|
|
54
|
... |
3668
|
|
|
|
|
|
|
} |
3669
|
|
|
|
|
|
|
|
3670
|
36
|
|
|
|
|
162
|
=cut |
3671
|
34
|
|
|
|
|
118
|
|
3672
|
34
|
|
|
|
|
667
|
{ |
3673
|
|
|
|
|
|
|
|
3674
|
|
|
|
|
|
|
my $proto = shift; |
3675
|
|
|
|
|
|
|
return sort keys %{ $proto->_plugins } unless @_; |
3676
|
33
|
100
|
|
|
|
585
|
my $plugin = shift; |
3677
|
|
|
|
|
|
|
return 1 if exists $proto->_plugins->{$plugin}; |
3678
|
35
|
|
|
|
|
133
|
return exists $proto->_plugins->{"Catalyst::Plugin::$plugin"}; |
3679
|
|
|
|
|
|
|
} |
3680
|
|
|
|
|
|
|
|
3681
|
81
|
|
|
|
|
235
|
my ( $proto, $plugin, $instant ) = @_; |
3682
|
|
|
|
|
|
|
my $class = ref $proto || $proto; |
3683
|
|
|
|
|
|
|
|
3684
|
|
|
|
|
|
|
load_class( $plugin ); |
3685
|
|
|
|
|
|
|
$class->log->warn( "$plugin inherits from 'Catalyst::Component' - this is deprecated and will not work in 5.81" ) |
3686
|
1217
|
|
|
1217
|
|
3299
|
if $plugin->isa( 'Catalyst::Component' ); |
3687
|
1217
|
50
|
|
|
|
3103
|
my $plugin_meta = Moose::Meta::Class->create($plugin); |
3688
|
1217
|
50
|
|
|
|
3656
|
if (!$plugin_meta->has_method('new') |
3689
|
|
|
|
|
|
|
&& ( $plugin->isa('Class::Accessor::Fast') || $plugin->isa('Class::Accessor') ) ) { |
3690
|
1217
|
|
|
|
|
2813
|
$plugin_meta->add_method('new', Moose::Object->meta->get_method('new')) |
3691
|
|
|
|
|
|
|
} |
3692
|
1217
|
100
|
|
|
|
3218
|
if (!$instant && !$proto->_plugins->{$plugin}) { |
3693
|
|
|
|
|
|
|
my $meta = Class::MOP::get_metaclass_by_name($class); |
3694
|
1213
|
|
66
|
|
|
4516
|
$meta->superclasses($plugin, $meta->superclasses); |
3695
|
|
|
|
|
|
|
} |
3696
|
1213
|
|
|
1213
|
|
56887
|
$proto->_plugins->{$plugin} = 1; |
3697
|
|
|
|
|
|
|
return $class; |
3698
|
|
|
|
|
|
|
} |
3699
|
19
|
|
|
19
|
|
565
|
|
3700
|
|
|
|
|
|
|
|
3701
|
|
|
|
|
|
|
my ( $class, $plugins ) = @_; |
3702
|
|
|
|
|
|
|
|
3703
|
|
|
|
|
|
|
$class->_plugins( {} ) unless $class->_plugins; |
3704
|
1213
|
|
|
|
|
9376
|
$plugins = [ grep { |
3705
|
|
|
|
|
|
|
m/Unicode::Encoding/ ? do { |
3706
|
|
|
|
|
|
|
$class->log->warn( |
3707
|
|
|
|
|
|
|
'Unicode::Encoding plugin is auto-applied,' |
3708
|
|
|
|
|
|
|
. ' please remove this from your appclass' |
3709
|
|
|
|
|
|
|
. ' and make sure to define "encoding" config' |
3710
|
|
|
|
|
|
|
); |
3711
|
|
|
|
|
|
|
unless (exists $class->config->{'encoding'}) { |
3712
|
|
|
|
|
|
|
$class->config->{'encoding'} = 'UTF-8'; |
3713
|
|
|
|
|
|
|
} |
3714
|
|
|
|
|
|
|
() } |
3715
|
|
|
|
|
|
|
: $_ |
3716
|
|
|
|
|
|
|
} @$plugins ]; |
3717
|
|
|
|
|
|
|
push @$plugins, $class->_default_plugins; |
3718
|
|
|
|
|
|
|
$plugins = Data::OptList::mkopt($plugins || []); |
3719
|
|
|
|
|
|
|
|
3720
|
|
|
|
|
|
|
my @plugins = map { |
3721
|
|
|
|
|
|
|
[ Catalyst::Utils::resolve_namespace( |
3722
|
|
|
|
|
|
|
$class . '::Plugin', |
3723
|
|
|
|
|
|
|
'Catalyst::Plugin', $_->[0] |
3724
|
175
|
|
|
175
|
1
|
34874
|
), |
3725
|
|
|
|
|
|
|
$_->[1], |
3726
|
175
|
|
100
|
|
|
1402
|
] |
3727
|
175
|
|
|
|
|
551
|
} @{ $plugins }; |
3728
|
175
|
|
|
|
|
474
|
|
3729
|
175
|
|
|
|
|
822
|
for my $plugin ( reverse @plugins ) { |
|
23
|
|
|
|
|
125
|
|
3730
|
|
|
|
|
|
|
load_class($plugin->[0], $plugin->[1]); |
3731
|
175
|
|
|
|
|
882
|
my $meta = find_meta($plugin->[0]); |
3732
|
175
|
100
|
|
|
|
830
|
next if $meta && $meta->isa('Moose::Meta::Role'); |
3733
|
4
|
100
|
|
|
|
16
|
|
3734
|
4
|
100
|
|
|
|
18
|
$class->_register_plugin($plugin->[0]); |
3735
|
|
|
|
|
|
|
} |
3736
|
|
|
|
|
|
|
|
3737
|
175
|
100
|
|
|
|
1211
|
my @roles = |
3738
|
151
|
|
|
|
|
1635
|
map { $_->[0]->name, $_->[1] } |
3739
|
|
|
|
|
|
|
grep { blessed($_->[0]) && $_->[0]->isa('Moose::Meta::Role') } |
3740
|
|
|
|
|
|
|
map { [find_meta($_->[0]), $_->[1]] } |
3741
|
175
|
100
|
|
|
|
1135
|
@plugins; |
3742
|
5
|
|
|
33
|
|
27
|
|
|
33
|
|
|
18
|
|
2188
|
|
3743
|
5
|
|
|
|
|
326
|
Moose::Util::apply_all_roles( |
3744
|
|
|
|
|
|
|
$class => @roles |
3745
|
|
|
|
|
|
|
) if @roles; |
3746
|
|
|
|
|
|
|
} |
3747
|
|
|
|
|
|
|
} |
3748
|
|
|
|
|
|
|
|
3749
|
|
|
|
|
|
|
=head2 default_middleware |
3750
|
|
|
|
|
|
|
|
3751
|
|
|
|
|
|
|
Returns a list of instantiated PSGI middleware objects which is the default |
3752
|
|
|
|
|
|
|
middleware that is active for this application (taking any configuration |
3753
|
|
|
|
|
|
|
options into account, excluding your custom added middleware via the C<psgi_middleware> |
3754
|
|
|
|
|
|
|
configuration option). You can override this method if you wish to change |
3755
|
|
|
|
|
|
|
the default middleware (although do so at risk since some middleware is vital |
3756
|
|
|
|
|
|
|
to application function.) |
3757
|
|
|
|
|
|
|
|
3758
|
|
|
|
|
|
|
The current default middleware list is: |
3759
|
|
|
|
|
|
|
|
3760
|
168
|
|
|
168
|
1
|
36107
|
Catalyst::Middleware::Stash |
3761
|
|
|
|
|
|
|
Plack::Middleware::HTTPExceptions |
3762
|
168
|
|
|
|
|
1435
|
Plack::Middleware::RemoveRedundantBody |
3763
|
|
|
|
|
|
|
Plack::Middleware::FixMissingBodyInRedirect |
3764
|
168
|
|
|
|
|
1041
|
Plack::Middleware::ContentLength |
3765
|
168
|
100
|
100
|
|
|
6144
|
Plack::Middleware::MethodOverride |
|
|
100
|
|
|
|
|
|
3766
|
11
|
|
|
258
|
|
70
|
Plack::Middleware::Head |
|
258
|
|
|
|
|
1545
|
|
3767
|
11
|
|
|
|
|
871
|
|
3768
|
|
|
|
|
|
|
If the configuration setting C<using_frontend_proxy> is true we add: |
3769
|
|
|
|
|
|
|
|
3770
|
|
|
|
|
|
|
Plack::Middleware::ReverseProxy |
3771
|
|
|
|
|
|
|
|
3772
|
|
|
|
|
|
|
If the configuration setting C<using_frontend_proxy_path> is true we add: |
3773
|
|
|
|
|
|
|
|
3774
|
|
|
|
|
|
|
Plack::Middleware::ReverseProxyPath |
3775
|
|
|
|
|
|
|
|
3776
|
|
|
|
|
|
|
But B<NOTE> that L<Plack::Middleware::ReverseProxyPath> is not a dependency of the |
3777
|
|
|
|
|
|
|
L<Catalyst> distribution so if you want to use this option you should add it to |
3778
|
|
|
|
|
|
|
your project distribution file. |
3779
|
|
|
|
|
|
|
|
3780
|
|
|
|
|
|
|
These middlewares will be added at L</setup_middleware> during the |
3781
|
|
|
|
|
|
|
L</setup> phase of application startup. |
3782
|
|
|
|
|
|
|
|
3783
|
|
|
|
|
|
|
=cut |
3784
|
|
|
|
|
|
|
|
3785
|
|
|
|
|
|
|
my $class = shift; |
3786
|
|
|
|
|
|
|
my @mw = ( |
3787
|
|
|
|
|
|
|
Catalyst::Middleware::Stash->new, |
3788
|
|
|
|
|
|
|
Plack::Middleware::HTTPExceptions->new, |
3789
|
|
|
|
|
|
|
Plack::Middleware::RemoveRedundantBody->new, |
3790
|
634
|
|
|
892
|
1
|
50072
|
Plack::Middleware::FixMissingBodyInRedirect->new, |
3791
|
634
|
100
|
|
|
|
2293
|
Plack::Middleware::ContentLength->new, |
|
627
|
|
|
|
|
3101
|
|
3792
|
7
|
|
|
|
|
12
|
Plack::Middleware::MethodOverride->new, |
3793
|
7
|
100
|
|
|
|
22
|
Plack::Middleware::Head->new); |
3794
|
4
|
|
|
|
|
23
|
|
3795
|
|
|
|
|
|
|
if($class->config->{using_frontend_proxy}) { |
3796
|
|
|
|
|
|
|
push @mw, Plack::Middleware::ReverseProxy->new; |
3797
|
|
|
|
|
|
|
} |
3798
|
564
|
|
|
567
|
|
1530
|
|
3799
|
564
|
|
33
|
|
|
2424
|
if($class->config->{using_frontend_proxy_path}) { |
3800
|
|
|
|
|
|
|
if(Class::Load::try_load_class('Plack::Middleware::ReverseProxyPath')) { |
3801
|
564
|
|
|
|
|
1865
|
push @mw, Plack::Middleware::ReverseProxyPath->new; |
3802
|
564
|
50
|
|
|
|
22727
|
} else { |
3803
|
|
|
|
|
|
|
$class->log->error("Cannot use configuration 'using_frontend_proxy_path' because 'Plack::Middleware::ReverseProxyPath' is not installed"); |
3804
|
564
|
|
|
|
|
3351
|
} |
3805
|
564
|
100
|
66
|
|
|
569962
|
} |
|
|
|
66
|
|
|
|
|
3806
|
|
|
|
|
|
|
|
3807
|
1
|
|
|
|
|
34
|
return @mw; |
3808
|
|
|
|
|
|
|
} |
3809
|
564
|
50
|
66
|
|
|
23144
|
|
3810
|
563
|
|
|
|
|
1482
|
=head2 registered_middlewares |
3811
|
563
|
|
|
|
|
2890
|
|
3812
|
|
|
|
|
|
|
Read only accessor that returns an array of all the middleware in the order |
3813
|
564
|
|
|
|
|
2742068
|
that they were added (which is the REVERSE of the order they will be applied). |
3814
|
564
|
|
|
|
|
1704
|
|
3815
|
|
|
|
|
|
|
The values returned will be either instances of L<Plack::Middleware> or of a |
3816
|
|
|
|
|
|
|
compatible interface, or a coderef, which is assumed to be inlined middleware |
3817
|
163
|
|
|
163
|
|
528
|
|
3818
|
|
|
|
|
|
|
=head2 setup_middleware (?@middleware) |
3819
|
|
|
|
|
|
|
|
3820
|
163
|
|
|
163
|
1
|
662
|
Read configuration information stored in configuration key C<psgi_middleware> or |
3821
|
|
|
|
|
|
|
from passed @args. |
3822
|
163
|
50
|
|
|
|
1396
|
|
3823
|
|
|
|
|
|
|
See under L</CONFIGURATION> information regarding C<psgi_middleware> and how |
3824
|
163
|
50
|
|
|
|
644
|
to use it to enable L<Plack::Middleware> |
|
643
|
|
|
|
|
1766
|
|
3825
|
0
|
|
|
|
|
0
|
|
3826
|
|
|
|
|
|
|
This method is automatically called during 'setup' of your application, so |
3827
|
|
|
|
|
|
|
you really don't need to invoke it. However you may do so if you find the idea |
3828
|
|
|
|
|
|
|
of loading middleware via configuration weird :). For example: |
3829
|
|
|
|
|
|
|
|
3830
|
0
|
0
|
|
|
|
0
|
package MyApp; |
3831
|
0
|
|
|
|
|
0
|
|
3832
|
|
|
|
|
|
|
use Catalyst; |
3833
|
0
|
|
|
|
|
0
|
|
3834
|
|
|
|
|
|
|
__PACKAGE__->setup_middleware('Head'); |
3835
|
|
|
|
|
|
|
__PACKAGE__->setup; |
3836
|
163
|
|
|
|
|
1435
|
|
3837
|
163
|
|
50
|
|
|
1283
|
When we read middleware definitions from configuration, we reverse the list |
3838
|
|
|
|
|
|
|
which sounds odd but is likely how you expect it to work if you have prior |
3839
|
|
|
|
|
|
|
experience with L<Plack::Builder> or if you previously used the plugin |
3840
|
642
|
|
|
|
|
31666
|
L<Catalyst::Plugin::EnableMiddleware> (which is now considered deprecated) |
3841
|
|
|
|
|
|
|
|
3842
|
|
|
|
|
|
|
So basically your middleware handles an incoming request from the first |
3843
|
|
|
|
|
|
|
registered middleware, down and handles the response from the last middleware |
3844
|
|
|
|
|
|
|
up. |
3845
|
|
|
|
|
|
|
|
3846
|
163
|
|
|
|
|
10277
|
=cut |
|
163
|
|
|
|
|
575
|
|
3847
|
|
|
|
|
|
|
|
3848
|
163
|
|
|
|
|
5026
|
my $class = shift; |
3849
|
642
|
|
|
|
|
2886
|
if(my $middleware = $class->_psgi_middleware) { |
3850
|
642
|
|
|
|
|
945526
|
my @mw = ($class->default_middleware, @$middleware); |
3851
|
642
|
100
|
100
|
|
|
8813
|
|
3852
|
|
|
|
|
|
|
if($class->config->{using_frontend_proxy}) { |
3853
|
563
|
|
|
|
|
6602
|
push @mw, Plack::Middleware::ReverseProxy->new; |
3854
|
|
|
|
|
|
|
} |
3855
|
|
|
|
|
|
|
|
3856
|
|
|
|
|
|
|
return @mw; |
3857
|
79
|
|
|
|
|
656
|
} else { |
3858
|
642
|
50
|
|
|
|
4326
|
die "You cannot call ->registered_middlewares until middleware has been setup"; |
3859
|
163
|
|
|
|
|
714
|
} |
|
642
|
|
|
|
|
5135
|
|
3860
|
|
|
|
|
|
|
} |
3861
|
|
|
|
|
|
|
|
3862
|
163
|
100
|
|
|
|
1110
|
my $class = shift; |
3863
|
|
|
|
|
|
|
my @middleware_definitions; |
3864
|
|
|
|
|
|
|
|
3865
|
|
|
|
|
|
|
# If someone calls this method you can add middleware with args. However if its |
3866
|
|
|
|
|
|
|
# called without an arg we need to setup the configuration middleware. |
3867
|
|
|
|
|
|
|
if(@_) { |
3868
|
|
|
|
|
|
|
@middleware_definitions = reverse(@_); |
3869
|
|
|
|
|
|
|
} else { |
3870
|
|
|
|
|
|
|
@middleware_definitions = reverse(@{$class->config->{'psgi_middleware'}||[]}) |
3871
|
|
|
|
|
|
|
unless $class->finalized_default_middleware; |
3872
|
|
|
|
|
|
|
$class->finalized_default_middleware(1); # Only do this once, just in case some people call setup over and over... |
3873
|
|
|
|
|
|
|
} |
3874
|
|
|
|
|
|
|
|
3875
|
|
|
|
|
|
|
my @middleware = (); |
3876
|
|
|
|
|
|
|
while(my $next = shift(@middleware_definitions)) { |
3877
|
|
|
|
|
|
|
if(ref $next) { |
3878
|
|
|
|
|
|
|
if(Scalar::Util::blessed $next && $next->can('wrap')) { |
3879
|
|
|
|
|
|
|
push @middleware, $next; |
3880
|
|
|
|
|
|
|
} elsif(ref $next eq 'CODE') { |
3881
|
|
|
|
|
|
|
push @middleware, $next; |
3882
|
|
|
|
|
|
|
} elsif(ref $next eq 'HASH') { |
3883
|
|
|
|
|
|
|
my $namespace = shift @middleware_definitions; |
3884
|
|
|
|
|
|
|
my $mw = $class->Catalyst::Utils::build_middleware($namespace, %$next); |
3885
|
|
|
|
|
|
|
push @middleware, $mw; |
3886
|
|
|
|
|
|
|
} else { |
3887
|
|
|
|
|
|
|
die "I can't handle middleware definition ${\ref $next}"; |
3888
|
|
|
|
|
|
|
} |
3889
|
|
|
|
|
|
|
} else { |
3890
|
|
|
|
|
|
|
my $mw = $class->Catalyst::Utils::build_middleware($next); |
3891
|
|
|
|
|
|
|
push @middleware, $mw; |
3892
|
|
|
|
|
|
|
} |
3893
|
|
|
|
|
|
|
} |
3894
|
|
|
|
|
|
|
|
3895
|
|
|
|
|
|
|
my @existing = @{$class->_psgi_middleware || []}; |
3896
|
|
|
|
|
|
|
$class->_psgi_middleware([@middleware,@existing,]); |
3897
|
|
|
|
|
|
|
} |
3898
|
|
|
|
|
|
|
|
3899
|
|
|
|
|
|
|
=head2 registered_data_handlers |
3900
|
|
|
|
|
|
|
|
3901
|
|
|
|
|
|
|
A read only copy of registered Data Handlers returned as a Hash, where each key |
3902
|
|
|
|
|
|
|
is a content type and each value is a subref that attempts to decode that content |
3903
|
|
|
|
|
|
|
type. |
3904
|
|
|
|
|
|
|
|
3905
|
143
|
|
|
143
|
1
|
425
|
=head2 setup_data_handlers (?@data_handler) |
3906
|
143
|
|
|
|
|
2572
|
|
3907
|
|
|
|
|
|
|
Read configuration information stored in configuration key C<data_handlers> or |
3908
|
|
|
|
|
|
|
from passed @args. |
3909
|
|
|
|
|
|
|
|
3910
|
|
|
|
|
|
|
See under L</CONFIGURATION> information regarding C<data_handlers>. |
3911
|
|
|
|
|
|
|
|
3912
|
|
|
|
|
|
|
This method is automatically called during 'setup' of your application, so |
3913
|
|
|
|
|
|
|
you really don't need to invoke it. |
3914
|
|
|
|
|
|
|
|
3915
|
143
|
50
|
|
|
|
24869
|
=head2 default_data_handlers |
3916
|
0
|
|
|
|
|
0
|
|
3917
|
|
|
|
|
|
|
Default Data Handlers that come bundled with L<Catalyst>. Currently there are |
3918
|
|
|
|
|
|
|
only two default data handlers, for 'application/json' and an alternative to |
3919
|
143
|
50
|
|
|
|
698
|
'application/x-www-form-urlencoded' which supposed nested form parameters via |
3920
|
0
|
0
|
|
|
|
0
|
L<CGI::Struct> or via L<CGI::Struct::XS> IF you've installed it. |
3921
|
0
|
|
|
|
|
0
|
|
3922
|
|
|
|
|
|
|
The 'application/json' data handler is used to parse incoming JSON into a Perl |
3923
|
0
|
|
|
|
|
0
|
data structure. It uses L<JSON::MaybeXS>. This allows you to fail back to |
3924
|
|
|
|
|
|
|
L<JSON::PP>, which is a Pure Perl JSON decoder, and has the smallest dependency |
3925
|
|
|
|
|
|
|
impact. |
3926
|
|
|
|
|
|
|
|
3927
|
143
|
|
|
|
|
727
|
Because we don't wish to add more dependencies to L<Catalyst>, if you wish to |
3928
|
|
|
|
|
|
|
use this new feature we recommend installing L<Cpanel::JSON::XS> in order to get |
3929
|
|
|
|
|
|
|
the best performance. You should add either to your dependency list |
3930
|
|
|
|
|
|
|
(Makefile.PL, dist.ini, cpanfile, etc.) |
3931
|
|
|
|
|
|
|
|
3932
|
|
|
|
|
|
|
=cut |
3933
|
|
|
|
|
|
|
|
3934
|
|
|
|
|
|
|
my $class = shift; |
3935
|
|
|
|
|
|
|
if(my $data_handlers = $class->_data_handlers) { |
3936
|
|
|
|
|
|
|
return %$data_handlers; |
3937
|
|
|
|
|
|
|
} else { |
3938
|
|
|
|
|
|
|
$class->setup_data_handlers; |
3939
|
|
|
|
|
|
|
return $class->registered_data_handlers; |
3940
|
|
|
|
|
|
|
} |
3941
|
|
|
|
|
|
|
} |
3942
|
|
|
|
|
|
|
|
3943
|
|
|
|
|
|
|
my ($class, %data_handler_callbacks) = @_; |
3944
|
|
|
|
|
|
|
%data_handler_callbacks = ( |
3945
|
|
|
|
|
|
|
%{$class->default_data_handlers}, |
3946
|
|
|
|
|
|
|
%{$class->config->{'data_handlers'}||+{}}, |
3947
|
|
|
|
|
|
|
%data_handler_callbacks); |
3948
|
|
|
|
|
|
|
|
3949
|
|
|
|
|
|
|
$class->_data_handlers(\%data_handler_callbacks); |
3950
|
|
|
|
|
|
|
} |
3951
|
|
|
|
|
|
|
|
3952
|
|
|
|
|
|
|
my ($class) = @_; |
3953
|
|
|
|
|
|
|
return +{ |
3954
|
|
|
|
|
|
|
'application/x-www-form-urlencoded' => sub { |
3955
|
|
|
|
|
|
|
my ($fh, $req) = @_; |
3956
|
|
|
|
|
|
|
my $params = $req->_use_hash_multivalue ? $req->body_parameters->mixed : $req->body_parameters; |
3957
|
|
|
|
|
|
|
Class::Load::load_first_existing_class('CGI::Struct::XS', 'CGI::Struct') |
3958
|
|
|
|
|
|
|
->can('build_cgi_struct')->($params); |
3959
|
|
|
|
|
|
|
}, |
3960
|
|
|
|
|
|
|
'application/json' => sub { |
3961
|
|
|
|
|
|
|
my ($fh, $req) = @_; |
3962
|
|
|
|
|
|
|
require JSON::MaybeXS; |
3963
|
|
|
|
|
|
|
my $slurped; |
3964
|
|
|
|
|
|
|
return eval { |
3965
|
|
|
|
|
|
|
local $/; |
3966
|
|
|
|
|
|
|
$slurped = $fh->getline; |
3967
|
|
|
|
|
|
|
JSON::MaybeXS::decode_json($slurped); # decode_json does utf8 decoding for us |
3968
|
|
|
|
|
|
|
} || Catalyst::Exception->throw(sprintf "Error Parsing POST '%s', Error: %s", (defined($slurped) ? $slurped : 'undef') ,$@); |
3969
|
143
|
|
|
143
|
1
|
1404
|
}, |
3970
|
143
|
50
|
|
|
|
929
|
}; |
3971
|
143
|
|
|
|
|
1179
|
} |
3972
|
|
|
|
|
|
|
|
3973
|
143
|
50
|
|
|
|
636
|
my ( $self, $error ) = @_; |
3974
|
0
|
|
|
|
|
0
|
if ( |
3975
|
|
|
|
|
|
|
!$self->config->{always_catch_http_exceptions} |
3976
|
|
|
|
|
|
|
&& blessed $error |
3977
|
143
|
|
|
|
|
824
|
&& ( |
3978
|
|
|
|
|
|
|
$error->can('as_psgi') |
3979
|
0
|
|
|
|
|
0
|
|| ( $error->can('code') |
3980
|
|
|
|
|
|
|
&& $error->code =~ m/^[1-5][0-9][0-9]$/ ) |
3981
|
|
|
|
|
|
|
) |
3982
|
|
|
|
|
|
|
) |
3983
|
|
|
|
|
|
|
{ |
3984
|
167
|
|
|
167
|
1
|
724
|
return 1; |
3985
|
167
|
|
|
|
|
387
|
} |
3986
|
|
|
|
|
|
|
} |
3987
|
|
|
|
|
|
|
|
3988
|
|
|
|
|
|
|
=head2 $c->stack |
3989
|
167
|
100
|
|
|
|
677
|
|
3990
|
2
|
|
|
|
|
6
|
Returns an arrayref of the internal execution stack (actions that are |
3991
|
|
|
|
|
|
|
currently executing). |
3992
|
165
|
100
|
|
|
|
1327
|
|
|
163
|
100
|
|
|
|
1004
|
|
3993
|
|
|
|
|
|
|
=head2 $c->stats |
3994
|
165
|
|
|
|
|
873
|
|
3995
|
|
|
|
|
|
|
Returns the current timing statistics object. By default Catalyst uses |
3996
|
|
|
|
|
|
|
L<Catalyst::Stats|Catalyst::Stats>, but can be set otherwise with |
3997
|
167
|
|
|
|
|
590
|
L<< stats_class|/"$c->stats_class" >>. |
3998
|
167
|
|
|
|
|
891
|
|
3999
|
14
|
100
|
|
|
|
38
|
Even if L<< -Stats|/"-Stats" >> is not enabled, the stats object is still |
4000
|
8
|
100
|
66
|
|
|
52
|
available. By enabling it with C<< $c->stats->enabled(1) >>, it can be used to |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
4001
|
2
|
|
|
|
|
9
|
profile explicitly, although MyApp.pm still won't profile nor output anything |
4002
|
|
|
|
|
|
|
by itself. |
4003
|
2
|
|
|
|
|
7
|
|
4004
|
|
|
|
|
|
|
=head2 $c->stats_class |
4005
|
4
|
|
|
|
|
8
|
|
4006
|
4
|
|
|
|
|
31
|
Returns or sets the stats (timing statistics) class. L<Catalyst::Stats|Catalyst::Stats> is used by default. |
4007
|
4
|
|
|
|
|
1364
|
|
4008
|
|
|
|
|
|
|
=head2 $app->stats_class_traits |
4009
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
4010
|
|
|
|
|
|
|
A arrayref of L<Moose::Role>s that are applied to the stats_class before creating it. |
4011
|
|
|
|
|
|
|
|
4012
|
6
|
|
|
|
|
38
|
=head2 $app->composed_stats_class |
4013
|
5
|
|
|
|
|
148
|
|
4014
|
|
|
|
|
|
|
this is the stats_class composed with any 'stats_class_traits'. You can |
4015
|
|
|
|
|
|
|
name the full namespace of the role, or a namespace suffix, which will then |
4016
|
|
|
|
|
|
|
be tried against the following standard namespace prefixes. |
4017
|
166
|
100
|
|
|
|
460
|
|
|
166
|
|
|
|
|
1444
|
|
4018
|
166
|
|
|
|
|
758
|
$MyApp::TraitFor::Stats::$trait_suffix |
4019
|
|
|
|
|
|
|
Catalyst::TraitFor::Stats::$trait_suffix |
4020
|
|
|
|
|
|
|
|
4021
|
|
|
|
|
|
|
So for example if you set: |
4022
|
|
|
|
|
|
|
|
4023
|
|
|
|
|
|
|
MyApp->stats_class_traits(['Foo']); |
4024
|
|
|
|
|
|
|
|
4025
|
|
|
|
|
|
|
We try each possible role in turn (and throw an error if none load) |
4026
|
|
|
|
|
|
|
|
4027
|
|
|
|
|
|
|
Foo |
4028
|
|
|
|
|
|
|
MyApp::TraitFor::Stats::Foo |
4029
|
|
|
|
|
|
|
Catalyst::TraitFor::Stats::Foo |
4030
|
|
|
|
|
|
|
|
4031
|
|
|
|
|
|
|
The namespace part 'TraitFor::Stats' was chosen to assist in backwards |
4032
|
|
|
|
|
|
|
compatibility with L<CatalystX::RoleApplicator> which previously provided |
4033
|
|
|
|
|
|
|
these features in a stand alone package. |
4034
|
|
|
|
|
|
|
|
4035
|
|
|
|
|
|
|
=head2 $c->use_stats |
4036
|
|
|
|
|
|
|
|
4037
|
|
|
|
|
|
|
Returns 1 when L<< stats collection|/"-Stats" >> is enabled. |
4038
|
|
|
|
|
|
|
|
4039
|
|
|
|
|
|
|
Note that this is a static method, not an accessor and should be overridden |
4040
|
|
|
|
|
|
|
by declaring C<sub use_stats { 1 }> in your MyApp.pm, not by calling C<< $c->use_stats(1) >>. |
4041
|
|
|
|
|
|
|
|
4042
|
|
|
|
|
|
|
=cut |
4043
|
|
|
|
|
|
|
|
4044
|
|
|
|
|
|
|
|
4045
|
|
|
|
|
|
|
|
4046
|
|
|
|
|
|
|
=head2 $c->write( $data ) |
4047
|
|
|
|
|
|
|
|
4048
|
|
|
|
|
|
|
Writes $data to the output stream. When using this method directly, you |
4049
|
|
|
|
|
|
|
will need to manually set the C<Content-Length> header to the length of |
4050
|
|
|
|
|
|
|
your output data, if known. |
4051
|
|
|
|
|
|
|
|
4052
|
|
|
|
|
|
|
=cut |
4053
|
|
|
|
|
|
|
|
4054
|
|
|
|
|
|
|
my $c = shift; |
4055
|
|
|
|
|
|
|
|
4056
|
|
|
|
|
|
|
# Finalize headers if someone manually writes output (for compat) |
4057
|
941
|
|
|
941
|
1
|
2075
|
$c->finalize_headers; |
4058
|
941
|
50
|
|
|
|
4024
|
|
4059
|
941
|
|
|
|
|
6619
|
return $c->response->write( @_ ); |
4060
|
|
|
|
|
|
|
} |
4061
|
0
|
|
|
|
|
0
|
|
4062
|
0
|
|
|
|
|
0
|
=head2 version |
4063
|
|
|
|
|
|
|
|
4064
|
|
|
|
|
|
|
Returns the Catalyst version number. Mostly useful for "powered by" |
4065
|
|
|
|
|
|
|
messages in template systems. |
4066
|
|
|
|
|
|
|
|
4067
|
163
|
|
|
163
|
1
|
681
|
=cut |
4068
|
|
|
|
|
|
|
|
4069
|
163
|
|
|
|
|
1252
|
|
4070
|
163
|
50
|
|
|
|
438
|
=head1 CONFIGURATION |
|
163
|
|
|
|
|
1357
|
|
4071
|
|
|
|
|
|
|
|
4072
|
|
|
|
|
|
|
There are a number of 'base' config variables which can be set: |
4073
|
163
|
|
|
|
|
1764
|
|
4074
|
|
|
|
|
|
|
=over |
4075
|
|
|
|
|
|
|
|
4076
|
|
|
|
|
|
|
=item * |
4077
|
163
|
|
|
163
|
1
|
577
|
|
4078
|
|
|
|
|
|
|
C<always_catch_http_exceptions> - As of version 5.90060 Catalyst |
4079
|
|
|
|
|
|
|
rethrows errors conforming to the interface described by |
4080
|
1
|
|
|
1
|
|
3
|
L<Plack::Middleware::HTTPExceptions> and lets the middleware deal with it. |
4081
|
1
|
50
|
|
|
|
25
|
Set true to get the deprecated behaviour and have Catalyst catch HTTP exceptions. |
4082
|
1
|
|
|
|
|
6
|
|
4083
|
|
|
|
|
|
|
=item * |
4084
|
|
|
|
|
|
|
|
4085
|
|
|
|
|
|
|
C<default_model> - The default model picked if you say C<< $c->model >>. See L<< /$c->model($name) >>. |
4086
|
5
|
|
|
5
|
|
17
|
|
4087
|
5
|
|
|
|
|
32
|
=item * |
4088
|
5
|
|
|
|
|
10
|
|
4089
|
5
|
|
66
|
|
|
8
|
C<default_view> - The default view to be rendered or returned when C<< $c->view >> is called. See L<< /$c->view($name) >>. |
4090
|
|
|
|
|
|
|
|
4091
|
|
|
|
|
|
|
=item * |
4092
|
|
|
|
|
|
|
|
4093
|
|
|
|
|
|
|
C<disable_component_resolution_regex_fallback> - Turns |
4094
|
|
|
|
|
|
|
off the deprecated component resolution functionality so |
4095
|
163
|
|
|
|
|
2194
|
that if any of the component methods (e.g. C<< $c->controller('Foo') >>) |
4096
|
|
|
|
|
|
|
are called then regex search will not be attempted on string values and |
4097
|
|
|
|
|
|
|
instead C<undef> will be returned. |
4098
|
|
|
|
|
|
|
|
4099
|
167
|
|
|
167
|
|
404
|
=item * |
4100
|
167
|
100
|
100
|
|
|
565
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
4101
|
|
|
|
|
|
|
C<home> - The application home directory. In an uninstalled application, |
4102
|
|
|
|
|
|
|
this is the top level application directory. In an installed application, |
4103
|
|
|
|
|
|
|
this will be the directory containing C<< MyApp.pm >>. |
4104
|
|
|
|
|
|
|
|
4105
|
|
|
|
|
|
|
=item * |
4106
|
|
|
|
|
|
|
|
4107
|
|
|
|
|
|
|
C<ignore_frontend_proxy> - See L</PROXY SUPPORT> |
4108
|
|
|
|
|
|
|
|
4109
|
|
|
|
|
|
|
=item * |
4110
|
14
|
|
|
|
|
73
|
|
4111
|
|
|
|
|
|
|
C<name> - The name of the application in debug messages and the debug and |
4112
|
|
|
|
|
|
|
welcome screens |
4113
|
|
|
|
|
|
|
|
4114
|
|
|
|
|
|
|
=item * |
4115
|
|
|
|
|
|
|
|
4116
|
|
|
|
|
|
|
C<parse_on_demand> - The request body (for example file uploads) will not be parsed |
4117
|
|
|
|
|
|
|
until it is accessed. This allows you to (for example) check authentication (and reject |
4118
|
|
|
|
|
|
|
the upload) before actually receiving all the data. See L</ON-DEMAND PARSER> |
4119
|
|
|
|
|
|
|
|
4120
|
|
|
|
|
|
|
=item * |
4121
|
|
|
|
|
|
|
|
4122
|
|
|
|
|
|
|
C<root> - The root directory for templates. Usually this is just a |
4123
|
|
|
|
|
|
|
subdirectory of the home directory, but you can set it to change the |
4124
|
|
|
|
|
|
|
templates to a different directory. |
4125
|
|
|
|
|
|
|
|
4126
|
|
|
|
|
|
|
=item * |
4127
|
|
|
|
|
|
|
|
4128
|
|
|
|
|
|
|
C<search_extra> - Array reference passed to Module::Pluggable to for additional |
4129
|
|
|
|
|
|
|
namespaces from which components will be loaded (and constructed and stored in |
4130
|
|
|
|
|
|
|
C<< $c->components >>). |
4131
|
|
|
|
|
|
|
|
4132
|
|
|
|
|
|
|
=item * |
4133
|
|
|
|
|
|
|
|
4134
|
|
|
|
|
|
|
C<show_internal_actions> - If true, causes internal actions such as C<< _DISPATCH >> |
4135
|
|
|
|
|
|
|
to be shown in hit debug tables in the test server. |
4136
|
|
|
|
|
|
|
|
4137
|
|
|
|
|
|
|
=item * |
4138
|
|
|
|
|
|
|
|
4139
|
|
|
|
|
|
|
C<use_request_uri_for_path> - Controls if the C<REQUEST_URI> or C<PATH_INFO> environment |
4140
|
|
|
|
|
|
|
variable should be used for determining the request path. |
4141
|
|
|
|
|
|
|
|
4142
|
|
|
|
|
|
|
Most web server environments pass the requested path to the application using environment variables, |
4143
|
|
|
|
|
|
|
from which Catalyst has to reconstruct the request base (i.e. the top level path to / in the application, |
4144
|
|
|
|
|
|
|
exposed as C<< $c->request->base >>) and the request path below that base. |
4145
|
|
|
|
|
|
|
|
4146
|
|
|
|
|
|
|
There are two methods of doing this, both of which have advantages and disadvantages. Which method is used |
4147
|
|
|
|
|
|
|
is determined by the C<< $c->config(use_request_uri_for_path) >> setting (which can either be true or false). |
4148
|
|
|
|
|
|
|
|
4149
|
|
|
|
|
|
|
=over |
4150
|
|
|
|
|
|
|
|
4151
|
|
|
|
|
|
|
=item use_request_uri_for_path => 0 |
4152
|
|
|
|
|
|
|
|
4153
|
|
|
|
|
|
|
This is the default (and the) traditional method that Catalyst has used for determining the path information. |
4154
|
|
|
|
|
|
|
The path is generated from a combination of the C<PATH_INFO> and C<SCRIPT_NAME> environment variables. |
4155
|
|
|
|
|
|
|
The allows the application to behave correctly when C<mod_rewrite> is being used to redirect requests |
4156
|
|
|
|
|
|
|
into the application, as these variables are adjusted by mod_rewrite to take account for the redirect. |
4157
|
|
|
|
|
|
|
|
4158
|
|
|
|
|
|
|
However this method has the major disadvantage that it is impossible to correctly decode some elements |
4159
|
|
|
|
|
|
|
of the path, as RFC 3875 says: "C<< Unlike a URI path, the PATH_INFO is not URL-encoded, and cannot |
4160
|
|
|
|
|
|
|
contain path-segment parameters. >>" This means PATH_INFO is B<always> decoded, and therefore Catalyst |
4161
|
|
|
|
|
|
|
can't distinguish / vs %2F in paths (in addition to other encoded values). |
4162
|
|
|
|
|
|
|
|
4163
|
|
|
|
|
|
|
=item use_request_uri_for_path => 1 |
4164
|
|
|
|
|
|
|
|
4165
|
|
|
|
|
|
|
This method uses the C<REQUEST_URI> and C<SCRIPT_NAME> environment variables. As C<REQUEST_URI> is never |
4166
|
|
|
|
|
|
|
decoded, this means that applications using this mode can correctly handle URIs including the %2F character |
4167
|
|
|
|
|
|
|
(i.e. with C<AllowEncodedSlashes> set to C<On> in Apache). |
4168
|
|
|
|
|
|
|
|
4169
|
|
|
|
|
|
|
Given that this method of path resolution is provably more correct, it is recommended that you use |
4170
|
19839
|
|
|
19839
|
1
|
67812
|
this unless you have a specific need to deploy your application in a non-standard environment, and you are |
4171
|
|
|
|
|
|
|
aware of the implications of not being able to handle encoded URI paths correctly. |
4172
|
|
|
|
|
|
|
|
4173
|
|
|
|
|
|
|
However it also means that in a number of cases when the app isn't installed directly at a path, but instead |
4174
|
|
|
|
|
|
|
is having paths rewritten into it (e.g. as a .cgi/fcgi in a public_html directory, with mod_rewrite in a |
4175
|
|
|
|
|
|
|
.htaccess file, or when SSI is used to rewrite pages into the app, or when sub-paths of the app are exposed |
4176
|
|
|
|
|
|
|
at other URIs than that which the app is 'normally' based at with C<mod_rewrite>), the resolution of |
4177
|
|
|
|
|
|
|
C<< $c->request->base >> will be incorrect. |
4178
|
|
|
|
|
|
|
|
4179
|
|
|
|
|
|
|
=back |
4180
|
|
|
|
|
|
|
|
4181
|
|
|
|
|
|
|
=item * |
4182
|
0
|
|
|
0
|
1
|
0
|
|
4183
|
|
|
|
|
|
|
C<using_frontend_proxy> - See L</PROXY SUPPORT>. |
4184
|
|
|
|
|
|
|
|
4185
|
0
|
|
|
|
|
0
|
=item * |
4186
|
|
|
|
|
|
|
|
4187
|
0
|
|
|
|
|
0
|
C<using_frontend_proxy_path> - Enabled L<Plack::Middleware::ReverseProxyPath> on your application (if |
4188
|
|
|
|
|
|
|
installed, otherwise log an error). This is useful if your application is not running on the |
4189
|
|
|
|
|
|
|
'root' (or /) of your host server. B<NOTE> if you use this feature you should add the required |
4190
|
|
|
|
|
|
|
middleware to your project dependency list since its not automatically a dependency of L<Catalyst>. |
4191
|
|
|
|
|
|
|
This has been done since not all people need this feature and we wish to restrict the growth of |
4192
|
|
|
|
|
|
|
L<Catalyst> dependencies. |
4193
|
|
|
|
|
|
|
|
4194
|
|
|
|
|
|
|
=item * |
4195
|
|
|
|
|
|
|
|
4196
|
|
|
|
|
|
|
C<encoding> - See L</ENCODING> |
4197
|
0
|
|
|
0
|
1
|
0
|
|
4198
|
|
|
|
|
|
|
This now defaults to 'UTF-8'. You my turn it off by setting this configuration |
4199
|
|
|
|
|
|
|
value to undef. |
4200
|
|
|
|
|
|
|
|
4201
|
|
|
|
|
|
|
=item * |
4202
|
|
|
|
|
|
|
|
4203
|
|
|
|
|
|
|
C<abort_chain_on_error_fix> |
4204
|
|
|
|
|
|
|
|
4205
|
|
|
|
|
|
|
Defaults to true. |
4206
|
|
|
|
|
|
|
|
4207
|
|
|
|
|
|
|
When there is an error in an action chain, the default behavior is to |
4208
|
|
|
|
|
|
|
abort the processing of the remaining actions to avoid running them |
4209
|
|
|
|
|
|
|
when the application is in an unexpected state. |
4210
|
|
|
|
|
|
|
|
4211
|
|
|
|
|
|
|
Before version 5.90070, the default used to be false. To keep the old |
4212
|
|
|
|
|
|
|
behaviour, you can explicitly set the value to false. E.g. |
4213
|
|
|
|
|
|
|
|
4214
|
|
|
|
|
|
|
__PACKAGE__->config(abort_chain_on_error_fix => 0); |
4215
|
|
|
|
|
|
|
|
4216
|
|
|
|
|
|
|
If this setting is set to false, then the remaining actions are |
4217
|
|
|
|
|
|
|
performed and the error is caught at the end of the chain. |
4218
|
|
|
|
|
|
|
|
4219
|
|
|
|
|
|
|
|
4220
|
|
|
|
|
|
|
=item * |
4221
|
|
|
|
|
|
|
|
4222
|
|
|
|
|
|
|
C<use_hash_multivalue_in_request> |
4223
|
|
|
|
|
|
|
|
4224
|
|
|
|
|
|
|
In L<Catalyst::Request> the methods C<query_parameters>, C<body_parametes> |
4225
|
|
|
|
|
|
|
and C<parameters> return a hashref where values might be scalar or an arrayref |
4226
|
|
|
|
|
|
|
depending on the incoming data. In many cases this can be undesirable as it |
4227
|
|
|
|
|
|
|
leads one to writing defensive code like the following: |
4228
|
|
|
|
|
|
|
|
4229
|
|
|
|
|
|
|
my ($val) = ref($c->req->parameters->{a}) ? |
4230
|
|
|
|
|
|
|
@{$c->req->parameters->{a}} : |
4231
|
|
|
|
|
|
|
$c->req->parameters->{a}; |
4232
|
|
|
|
|
|
|
|
4233
|
|
|
|
|
|
|
Setting this configuration item to true will make L<Catalyst> populate the |
4234
|
|
|
|
|
|
|
attributes underlying these methods with an instance of L<Hash::MultiValue> |
4235
|
|
|
|
|
|
|
which is used by L<Plack::Request> and others to solve this very issue. You |
4236
|
|
|
|
|
|
|
may prefer this behavior to the default, if so enable this option (be warned |
4237
|
|
|
|
|
|
|
if you enable it in a legacy application we are not sure if it is completely |
4238
|
|
|
|
|
|
|
backwardly compatible). |
4239
|
|
|
|
|
|
|
|
4240
|
|
|
|
|
|
|
=item * |
4241
|
|
|
|
|
|
|
|
4242
|
|
|
|
|
|
|
C<skip_complex_post_part_handling> |
4243
|
|
|
|
|
|
|
|
4244
|
|
|
|
|
|
|
When creating body parameters from a POST, if we run into a multipart POST |
4245
|
|
|
|
|
|
|
that does not contain uploads, but instead contains inlined complex data |
4246
|
|
|
|
|
|
|
(very uncommon) we cannot reliably convert that into field => value pairs. So |
4247
|
|
|
|
|
|
|
instead we create an instance of L<Catalyst::Request::PartData>. If this causes |
4248
|
|
|
|
|
|
|
issue for you, you can disable this by setting C<skip_complex_post_part_handling> |
4249
|
|
|
|
|
|
|
to true (default is false). |
4250
|
|
|
|
|
|
|
|
4251
|
|
|
|
|
|
|
=item * |
4252
|
|
|
|
|
|
|
|
4253
|
|
|
|
|
|
|
C<skip_body_param_unicode_decoding> |
4254
|
|
|
|
|
|
|
|
4255
|
|
|
|
|
|
|
Generally we decode incoming POST params based on your declared encoding (the |
4256
|
|
|
|
|
|
|
default for this is to decode UTF-8). If this is causing you trouble and you |
4257
|
|
|
|
|
|
|
do not wish to turn all encoding support off (with the C<encoding> configuration |
4258
|
|
|
|
|
|
|
parameter) you may disable this step atomically by setting this configuration |
4259
|
|
|
|
|
|
|
parameter to true. |
4260
|
|
|
|
|
|
|
|
4261
|
|
|
|
|
|
|
=item * |
4262
|
|
|
|
|
|
|
|
4263
|
|
|
|
|
|
|
C<do_not_decode_query> |
4264
|
|
|
|
|
|
|
|
4265
|
|
|
|
|
|
|
If true, then do not try to character decode any wide characters in your |
4266
|
|
|
|
|
|
|
request URL query or keywords. Most readings of the relevant specifications |
4267
|
|
|
|
|
|
|
suggest these should be UTF-* encoded, which is the default that L<Catalyst> |
4268
|
|
|
|
|
|
|
will use, however if you are creating a lot of URLs manually or have external |
4269
|
|
|
|
|
|
|
evil clients, this might cause you trouble. If you find the changes introduced |
4270
|
|
|
|
|
|
|
in Catalyst version 5.90080+ break some of your query code, you may disable |
4271
|
|
|
|
|
|
|
the UTF-8 decoding globally using this configuration. |
4272
|
|
|
|
|
|
|
|
4273
|
|
|
|
|
|
|
This setting takes precedence over C<default_query_encoding> |
4274
|
|
|
|
|
|
|
|
4275
|
|
|
|
|
|
|
=item * |
4276
|
|
|
|
|
|
|
|
4277
|
|
|
|
|
|
|
C<do_not_check_query_encoding> |
4278
|
|
|
|
|
|
|
|
4279
|
|
|
|
|
|
|
Catalyst versions 5.90080 - 5.90106 would decode query parts of an incoming |
4280
|
|
|
|
|
|
|
request but would not raise an exception when the decoding failed due to |
4281
|
|
|
|
|
|
|
incorrect unicode. It now does, but if this change is giving you trouble |
4282
|
|
|
|
|
|
|
you may disable it by setting this configuration to true. |
4283
|
|
|
|
|
|
|
|
4284
|
|
|
|
|
|
|
=item * |
4285
|
|
|
|
|
|
|
|
4286
|
|
|
|
|
|
|
C<default_query_encoding> |
4287
|
|
|
|
|
|
|
|
4288
|
|
|
|
|
|
|
By default we decode query and keywords in your request URL using UTF-8, which |
4289
|
|
|
|
|
|
|
is our reading of the relevant specifications. This setting allows one to |
4290
|
|
|
|
|
|
|
specify a fixed value for how to decode your query. You might need this if |
4291
|
|
|
|
|
|
|
you are doing a lot of custom encoding of your URLs and not using UTF-8. |
4292
|
|
|
|
|
|
|
|
4293
|
|
|
|
|
|
|
=item * |
4294
|
|
|
|
|
|
|
|
4295
|
|
|
|
|
|
|
C<use_chained_args_0_special_case> |
4296
|
|
|
|
|
|
|
|
4297
|
|
|
|
|
|
|
In older versions of Catalyst, when more than one action matched the same path |
4298
|
|
|
|
|
|
|
AND all those matching actions declared Args(0), we'd break the tie by choosing |
4299
|
|
|
|
|
|
|
the first action defined. We now normalized how Args(0) works so that it |
4300
|
|
|
|
|
|
|
follows the same rule as Args(N), which is to say when we need to break a tie |
4301
|
|
|
|
|
|
|
we choose the LAST action defined. If this breaks your code and you don't |
4302
|
|
|
|
|
|
|
have time to update to follow the new normalized approach, you may set this |
4303
|
|
|
|
|
|
|
value to true and it will globally revert to the original chaining behavior. |
4304
|
|
|
|
|
|
|
|
4305
|
|
|
|
|
|
|
=item * |
4306
|
|
|
|
|
|
|
|
4307
|
|
|
|
|
|
|
C<psgi_middleware> - See L<PSGI MIDDLEWARE>. |
4308
|
|
|
|
|
|
|
|
4309
|
|
|
|
|
|
|
=item * |
4310
|
|
|
|
|
|
|
|
4311
|
|
|
|
|
|
|
C<data_handlers> - See L<DATA HANDLERS>. |
4312
|
|
|
|
|
|
|
|
4313
|
|
|
|
|
|
|
=item * |
4314
|
|
|
|
|
|
|
|
4315
|
|
|
|
|
|
|
C<stats_class_traits> |
4316
|
|
|
|
|
|
|
|
4317
|
|
|
|
|
|
|
An arrayref of L<Moose::Role>s that get composed into your stats class. |
4318
|
|
|
|
|
|
|
|
4319
|
|
|
|
|
|
|
=item * |
4320
|
|
|
|
|
|
|
|
4321
|
|
|
|
|
|
|
C<request_class_traits> |
4322
|
|
|
|
|
|
|
|
4323
|
|
|
|
|
|
|
An arrayref of L<Moose::Role>s that get composed into your request class. |
4324
|
|
|
|
|
|
|
|
4325
|
|
|
|
|
|
|
=item * |
4326
|
|
|
|
|
|
|
|
4327
|
|
|
|
|
|
|
C<response_class_traits> |
4328
|
|
|
|
|
|
|
|
4329
|
|
|
|
|
|
|
An arrayref of L<Moose::Role>s that get composed into your response class. |
4330
|
|
|
|
|
|
|
|
4331
|
|
|
|
|
|
|
=item * |
4332
|
|
|
|
|
|
|
|
4333
|
|
|
|
|
|
|
C<inject_components> |
4334
|
|
|
|
|
|
|
|
4335
|
|
|
|
|
|
|
A Hashref of L<Catalyst::Component> subclasses that are 'injected' into configuration. |
4336
|
|
|
|
|
|
|
For example: |
4337
|
|
|
|
|
|
|
|
4338
|
|
|
|
|
|
|
MyApp->config({ |
4339
|
|
|
|
|
|
|
inject_components => { |
4340
|
|
|
|
|
|
|
'Controller::Err' => { from_component => 'Local::Controller::Errors' }, |
4341
|
|
|
|
|
|
|
'Model::Zoo' => { from_component => 'Local::Model::Foo' }, |
4342
|
|
|
|
|
|
|
'Model::Foo' => { from_component => 'Local::Model::Foo', roles => ['TestRole'] }, |
4343
|
|
|
|
|
|
|
}, |
4344
|
|
|
|
|
|
|
'Controller::Err' => { a => 100, b=>200, namespace=>'error' }, |
4345
|
|
|
|
|
|
|
'Model::Zoo' => { a => 2 }, |
4346
|
|
|
|
|
|
|
'Model::Foo' => { a => 100 }, |
4347
|
|
|
|
|
|
|
}); |
4348
|
|
|
|
|
|
|
|
4349
|
|
|
|
|
|
|
Generally L<Catalyst> looks for components in your Model/View or Controller directories. |
4350
|
|
|
|
|
|
|
However for cases when you which to use an existing component and you don't need any |
4351
|
|
|
|
|
|
|
customization (where for when you can apply a role to customize it) you may inject those |
4352
|
|
|
|
|
|
|
components into your application. Please note any configuration should be done 'in the |
4353
|
|
|
|
|
|
|
normal way', with a key under configuration named after the component affix, as in the |
4354
|
|
|
|
|
|
|
above example. |
4355
|
|
|
|
|
|
|
|
4356
|
|
|
|
|
|
|
Using this type of injection allows you to construct significant amounts of your application |
4357
|
|
|
|
|
|
|
with only configuration!. This may or may not lead to increased code understanding. |
4358
|
|
|
|
|
|
|
|
4359
|
|
|
|
|
|
|
Please not you may also call the ->inject_components application method as well, although |
4360
|
|
|
|
|
|
|
you must do so BEFORE setup. |
4361
|
|
|
|
|
|
|
|
4362
|
|
|
|
|
|
|
=back |
4363
|
|
|
|
|
|
|
|
4364
|
|
|
|
|
|
|
=head1 EXCEPTIONS |
4365
|
|
|
|
|
|
|
|
4366
|
|
|
|
|
|
|
Generally when you throw an exception inside an Action (or somewhere in |
4367
|
|
|
|
|
|
|
your stack, such as in a model that an Action is calling) that exception |
4368
|
|
|
|
|
|
|
is caught by Catalyst and unless you either catch it yourself (via eval |
4369
|
|
|
|
|
|
|
or something like L<Try::Tiny> or by reviewing the L</error> stack, it |
4370
|
|
|
|
|
|
|
will eventually reach L</finalize_errors> and return either the debugging |
4371
|
|
|
|
|
|
|
error stack page, or the default error page. However, if your exception |
4372
|
|
|
|
|
|
|
can be caught by L<Plack::Middleware::HTTPExceptions>, L<Catalyst> will |
4373
|
|
|
|
|
|
|
instead rethrow it so that it can be handled by that middleware (which |
4374
|
|
|
|
|
|
|
is part of the default middleware). For example this would allow |
4375
|
|
|
|
|
|
|
|
4376
|
|
|
|
|
|
|
use HTTP::Throwable::Factory 'http_throw'; |
4377
|
|
|
|
|
|
|
|
4378
|
|
|
|
|
|
|
sub throws_exception :Local { |
4379
|
|
|
|
|
|
|
my ($self, $c) = @_; |
4380
|
|
|
|
|
|
|
|
4381
|
|
|
|
|
|
|
http_throw(SeeOther => { location => |
4382
|
|
|
|
|
|
|
$c->uri_for($self->action_for('redirect')) }); |
4383
|
|
|
|
|
|
|
|
4384
|
|
|
|
|
|
|
} |
4385
|
|
|
|
|
|
|
|
4386
|
|
|
|
|
|
|
=head1 INTERNAL ACTIONS |
4387
|
|
|
|
|
|
|
|
4388
|
|
|
|
|
|
|
Catalyst uses internal actions like C<_DISPATCH>, C<_BEGIN>, C<_AUTO>, |
4389
|
|
|
|
|
|
|
C<_ACTION>, and C<_END>. These are by default not shown in the private |
4390
|
|
|
|
|
|
|
action table, but you can make them visible with a config parameter. |
4391
|
|
|
|
|
|
|
|
4392
|
|
|
|
|
|
|
MyApp->config(show_internal_actions => 1); |
4393
|
|
|
|
|
|
|
|
4394
|
|
|
|
|
|
|
=head1 ON-DEMAND PARSER |
4395
|
|
|
|
|
|
|
|
4396
|
|
|
|
|
|
|
The request body is usually parsed at the beginning of a request, |
4397
|
|
|
|
|
|
|
but if you want to handle input yourself, you can enable on-demand |
4398
|
|
|
|
|
|
|
parsing with a config parameter. |
4399
|
|
|
|
|
|
|
|
4400
|
|
|
|
|
|
|
MyApp->config(parse_on_demand => 1); |
4401
|
|
|
|
|
|
|
|
4402
|
|
|
|
|
|
|
=head1 PROXY SUPPORT |
4403
|
|
|
|
|
|
|
|
4404
|
|
|
|
|
|
|
Many production servers operate using the common double-server approach, |
4405
|
|
|
|
|
|
|
with a lightweight frontend web server passing requests to a larger |
4406
|
|
|
|
|
|
|
backend server. An application running on the backend server must deal |
4407
|
|
|
|
|
|
|
with two problems: the remote user always appears to be C<127.0.0.1> and |
4408
|
|
|
|
|
|
|
the server's hostname will appear to be C<localhost> regardless of the |
4409
|
|
|
|
|
|
|
virtual host that the user connected through. |
4410
|
|
|
|
|
|
|
|
4411
|
|
|
|
|
|
|
Catalyst will automatically detect this situation when you are running |
4412
|
|
|
|
|
|
|
the frontend and backend servers on the same machine. The following |
4413
|
|
|
|
|
|
|
changes are made to the request. |
4414
|
|
|
|
|
|
|
|
4415
|
|
|
|
|
|
|
$c->req->address is set to the user's real IP address, as read from |
4416
|
|
|
|
|
|
|
the HTTP X-Forwarded-For header. |
4417
|
|
|
|
|
|
|
|
4418
|
|
|
|
|
|
|
The host value for $c->req->base and $c->req->uri is set to the real |
4419
|
|
|
|
|
|
|
host, as read from the HTTP X-Forwarded-Host header. |
4420
|
|
|
|
|
|
|
|
4421
|
|
|
|
|
|
|
Additionally, you may be running your backend application on an insecure |
4422
|
|
|
|
|
|
|
connection (port 80) while your frontend proxy is running under SSL. If there |
4423
|
|
|
|
|
|
|
is a discrepancy in the ports, use the HTTP header C<X-Forwarded-Port> to |
4424
|
|
|
|
|
|
|
tell Catalyst what port the frontend listens on. This will allow all URIs to |
4425
|
|
|
|
|
|
|
be created properly. |
4426
|
|
|
|
|
|
|
|
4427
|
|
|
|
|
|
|
In the case of passing in: |
4428
|
|
|
|
|
|
|
|
4429
|
|
|
|
|
|
|
X-Forwarded-Port: 443 |
4430
|
|
|
|
|
|
|
|
4431
|
|
|
|
|
|
|
All calls to C<uri_for> will result in an https link, as is expected. |
4432
|
|
|
|
|
|
|
|
4433
|
|
|
|
|
|
|
Obviously, your web server must support these headers for this to work. |
4434
|
|
|
|
|
|
|
|
4435
|
|
|
|
|
|
|
In a more complex server farm environment where you may have your |
4436
|
|
|
|
|
|
|
frontend proxy server(s) on different machines, you will need to set a |
4437
|
|
|
|
|
|
|
configuration option to tell Catalyst to read the proxied data from the |
4438
|
|
|
|
|
|
|
headers. |
4439
|
|
|
|
|
|
|
|
4440
|
|
|
|
|
|
|
MyApp->config(using_frontend_proxy => 1); |
4441
|
|
|
|
|
|
|
|
4442
|
|
|
|
|
|
|
If you do not wish to use the proxy support at all, you may set: |
4443
|
|
|
|
|
|
|
|
4444
|
|
|
|
|
|
|
MyApp->config(ignore_frontend_proxy => 0); |
4445
|
|
|
|
|
|
|
|
4446
|
|
|
|
|
|
|
=head2 Note about psgi files |
4447
|
|
|
|
|
|
|
|
4448
|
|
|
|
|
|
|
Note that if you supply your own .psgi file, calling |
4449
|
|
|
|
|
|
|
C<< MyApp->psgi_app(@_); >>, then B<this will not happen automatically>. |
4450
|
|
|
|
|
|
|
|
4451
|
|
|
|
|
|
|
You either need to apply L<Plack::Middleware::ReverseProxy> yourself |
4452
|
|
|
|
|
|
|
in your psgi, for example: |
4453
|
|
|
|
|
|
|
|
4454
|
|
|
|
|
|
|
builder { |
4455
|
|
|
|
|
|
|
enable "Plack::Middleware::ReverseProxy"; |
4456
|
|
|
|
|
|
|
MyApp->psgi_app |
4457
|
|
|
|
|
|
|
}; |
4458
|
|
|
|
|
|
|
|
4459
|
|
|
|
|
|
|
This will unconditionally add the ReverseProxy support, or you need to call |
4460
|
|
|
|
|
|
|
C<< $app = MyApp->apply_default_middlewares($app) >> (to conditionally |
4461
|
|
|
|
|
|
|
apply the support depending upon your config). |
4462
|
|
|
|
|
|
|
|
4463
|
|
|
|
|
|
|
See L<Catalyst::PSGI> for more information. |
4464
|
|
|
|
|
|
|
|
4465
|
|
|
|
|
|
|
=head1 THREAD SAFETY |
4466
|
|
|
|
|
|
|
|
4467
|
|
|
|
|
|
|
Catalyst has been tested under Apache 2's threading C<mpm_worker>, |
4468
|
|
|
|
|
|
|
C<mpm_winnt>, and the standalone forking HTTP server on Windows. We |
4469
|
|
|
|
|
|
|
believe the Catalyst core to be thread-safe. |
4470
|
|
|
|
|
|
|
|
4471
|
|
|
|
|
|
|
If you plan to operate in a threaded environment, remember that all other |
4472
|
|
|
|
|
|
|
modules you are using must also be thread-safe. Some modules, most notably |
4473
|
|
|
|
|
|
|
L<DBD::SQLite>, are not thread-safe. |
4474
|
|
|
|
|
|
|
|
4475
|
|
|
|
|
|
|
=head1 DATA HANDLERS |
4476
|
|
|
|
|
|
|
|
4477
|
|
|
|
|
|
|
The L<Catalyst::Request> object uses L<HTTP::Body> to populate 'classic' HTML |
4478
|
|
|
|
|
|
|
form parameters and URL search query fields. However it has become common |
4479
|
|
|
|
|
|
|
for various alternative content types to be PUT or POSTed to your controllers |
4480
|
|
|
|
|
|
|
and actions. People working on RESTful APIs, or using AJAX often use JSON, |
4481
|
|
|
|
|
|
|
XML and other content types when communicating with an application server. In |
4482
|
|
|
|
|
|
|
order to better support this use case, L<Catalyst> defines a global configuration |
4483
|
|
|
|
|
|
|
option, C<data_handlers>, which lets you associate a content type with a coderef |
4484
|
|
|
|
|
|
|
that parses that content type into something Perl can readily access. |
4485
|
|
|
|
|
|
|
|
4486
|
|
|
|
|
|
|
package MyApp::Web; |
4487
|
|
|
|
|
|
|
|
4488
|
|
|
|
|
|
|
use Catalyst; |
4489
|
|
|
|
|
|
|
use JSON::MaybeXS; |
4490
|
|
|
|
|
|
|
|
4491
|
|
|
|
|
|
|
__PACKAGE__->config( |
4492
|
|
|
|
|
|
|
data_handlers => { |
4493
|
|
|
|
|
|
|
'application/json' => sub { local $/; decode_json $_->getline }, |
4494
|
|
|
|
|
|
|
}, |
4495
|
|
|
|
|
|
|
## Any other configuration. |
4496
|
|
|
|
|
|
|
); |
4497
|
|
|
|
|
|
|
|
4498
|
|
|
|
|
|
|
__PACKAGE__->setup; |
4499
|
|
|
|
|
|
|
|
4500
|
|
|
|
|
|
|
By default L<Catalyst> comes with a generic JSON data handler similar to the |
4501
|
|
|
|
|
|
|
example given above, which uses L<JSON::MaybeXS> to provide either L<JSON::PP> |
4502
|
|
|
|
|
|
|
(a pure Perl, dependency free JSON parser) or L<Cpanel::JSON::XS> if you have |
4503
|
|
|
|
|
|
|
it installed (if you want the faster XS parser, add it to you project Makefile.PL |
4504
|
|
|
|
|
|
|
or dist.ini, cpanfile, etc.) |
4505
|
|
|
|
|
|
|
|
4506
|
|
|
|
|
|
|
The C<data_handlers> configuration is a hashref whose keys are HTTP Content-Types |
4507
|
|
|
|
|
|
|
(matched against the incoming request type using a regexp such as to be case |
4508
|
|
|
|
|
|
|
insensitive) and whose values are coderefs that receive a localized version of |
4509
|
|
|
|
|
|
|
C<$_> which is a filehandle object pointing to received body. |
4510
|
|
|
|
|
|
|
|
4511
|
|
|
|
|
|
|
This feature is considered an early access release and we reserve the right |
4512
|
|
|
|
|
|
|
to alter the interface in order to provide a performant and secure solution to |
4513
|
|
|
|
|
|
|
alternative request body content. Your reports welcomed! |
4514
|
|
|
|
|
|
|
|
4515
|
|
|
|
|
|
|
=head1 PSGI MIDDLEWARE |
4516
|
|
|
|
|
|
|
|
4517
|
|
|
|
|
|
|
You can define middleware, defined as L<Plack::Middleware> or a compatible |
4518
|
|
|
|
|
|
|
interface in configuration. Your middleware definitions are in the form of an |
4519
|
|
|
|
|
|
|
arrayref under the configuration key C<psgi_middleware>. Here's an example |
4520
|
|
|
|
|
|
|
with details to follow: |
4521
|
|
|
|
|
|
|
|
4522
|
|
|
|
|
|
|
package MyApp::Web; |
4523
|
|
|
|
|
|
|
|
4524
|
|
|
|
|
|
|
use Catalyst; |
4525
|
|
|
|
|
|
|
use Plack::Middleware::StackTrace; |
4526
|
|
|
|
|
|
|
|
4527
|
|
|
|
|
|
|
my $stacktrace_middleware = Plack::Middleware::StackTrace->new; |
4528
|
|
|
|
|
|
|
|
4529
|
|
|
|
|
|
|
__PACKAGE__->config( |
4530
|
|
|
|
|
|
|
'psgi_middleware', [ |
4531
|
|
|
|
|
|
|
'Debug', |
4532
|
|
|
|
|
|
|
'+MyApp::Custom', |
4533
|
|
|
|
|
|
|
$stacktrace_middleware, |
4534
|
|
|
|
|
|
|
'Session' => {store => 'File'}, |
4535
|
|
|
|
|
|
|
sub { |
4536
|
|
|
|
|
|
|
my $app = shift; |
4537
|
|
|
|
|
|
|
return sub { |
4538
|
|
|
|
|
|
|
my $env = shift; |
4539
|
|
|
|
|
|
|
$env->{myapp.customkey} = 'helloworld'; |
4540
|
|
|
|
|
|
|
$app->($env); |
4541
|
|
|
|
|
|
|
}, |
4542
|
|
|
|
|
|
|
}, |
4543
|
|
|
|
|
|
|
], |
4544
|
|
|
|
|
|
|
); |
4545
|
|
|
|
|
|
|
|
4546
|
|
|
|
|
|
|
__PACKAGE__->setup; |
4547
|
|
|
|
|
|
|
|
4548
|
|
|
|
|
|
|
So the general form is: |
4549
|
|
|
|
|
|
|
|
4550
|
|
|
|
|
|
|
__PACKAGE__->config(psgi_middleware => \@middleware_definitions); |
4551
|
|
|
|
|
|
|
|
4552
|
|
|
|
|
|
|
Where C<@middleware> is one or more of the following, applied in the REVERSE of |
4553
|
|
|
|
|
|
|
the order listed (to make it function similarly to L<Plack::Builder>: |
4554
|
|
|
|
|
|
|
|
4555
|
|
|
|
|
|
|
Alternatively, you may also define middleware by calling the L</setup_middleware> |
4556
|
|
|
|
|
|
|
package method: |
4557
|
|
|
|
|
|
|
|
4558
|
|
|
|
|
|
|
package MyApp::Web; |
4559
|
|
|
|
|
|
|
|
4560
|
|
|
|
|
|
|
use Catalyst; |
4561
|
|
|
|
|
|
|
|
4562
|
|
|
|
|
|
|
__PACKAGE__->setup_middleware( \@middleware_definitions); |
4563
|
|
|
|
|
|
|
__PACKAGE__->setup; |
4564
|
|
|
|
|
|
|
|
4565
|
|
|
|
|
|
|
In the case where you do both (use 'setup_middleware' and configuration) the |
4566
|
|
|
|
|
|
|
package call to setup_middleware will be applied earlier (in other words its |
4567
|
|
|
|
|
|
|
middleware will wrap closer to the application). Keep this in mind since in |
4568
|
|
|
|
|
|
|
some cases the order of middleware is important. |
4569
|
|
|
|
|
|
|
|
4570
|
|
|
|
|
|
|
The two approaches are not exclusive. |
4571
|
|
|
|
|
|
|
|
4572
|
|
|
|
|
|
|
=over 4 |
4573
|
|
|
|
|
|
|
|
4574
|
|
|
|
|
|
|
=item Middleware Object |
4575
|
|
|
|
|
|
|
|
4576
|
|
|
|
|
|
|
An already initialized object that conforms to the L<Plack::Middleware> |
4577
|
|
|
|
|
|
|
specification: |
4578
|
|
|
|
|
|
|
|
4579
|
|
|
|
|
|
|
my $stacktrace_middleware = Plack::Middleware::StackTrace->new; |
4580
|
|
|
|
|
|
|
|
4581
|
|
|
|
|
|
|
__PACKAGE__->config( |
4582
|
|
|
|
|
|
|
'psgi_middleware', [ |
4583
|
|
|
|
|
|
|
$stacktrace_middleware, |
4584
|
|
|
|
|
|
|
]); |
4585
|
|
|
|
|
|
|
|
4586
|
|
|
|
|
|
|
|
4587
|
|
|
|
|
|
|
=item coderef |
4588
|
|
|
|
|
|
|
|
4589
|
|
|
|
|
|
|
A coderef that is an inlined middleware: |
4590
|
|
|
|
|
|
|
|
4591
|
|
|
|
|
|
|
__PACKAGE__->config( |
4592
|
|
|
|
|
|
|
'psgi_middleware', [ |
4593
|
|
|
|
|
|
|
sub { |
4594
|
|
|
|
|
|
|
my $app = shift; |
4595
|
|
|
|
|
|
|
return sub { |
4596
|
|
|
|
|
|
|
my $env = shift; |
4597
|
|
|
|
|
|
|
if($env->{PATH_INFO} =~m/forced/) { |
4598
|
|
|
|
|
|
|
Plack::App::File |
4599
|
|
|
|
|
|
|
->new(file=>TestApp->path_to(qw/share static forced.txt/)) |
4600
|
|
|
|
|
|
|
->call($env); |
4601
|
|
|
|
|
|
|
} else { |
4602
|
|
|
|
|
|
|
return $app->($env); |
4603
|
|
|
|
|
|
|
} |
4604
|
|
|
|
|
|
|
}, |
4605
|
|
|
|
|
|
|
}, |
4606
|
|
|
|
|
|
|
]); |
4607
|
|
|
|
|
|
|
|
4608
|
|
|
|
|
|
|
|
4609
|
|
|
|
|
|
|
|
4610
|
|
|
|
|
|
|
=item a scalar |
4611
|
|
|
|
|
|
|
|
4612
|
|
|
|
|
|
|
We assume the scalar refers to a namespace after normalizing it using the |
4613
|
|
|
|
|
|
|
following rules: |
4614
|
|
|
|
|
|
|
|
4615
|
|
|
|
|
|
|
(1) If the scalar is prefixed with a "+" (as in C<+MyApp::Foo>) then the full string |
4616
|
|
|
|
|
|
|
is assumed to be 'as is', and we just install and use the middleware. |
4617
|
|
|
|
|
|
|
|
4618
|
|
|
|
|
|
|
(2) If the scalar begins with "Plack::Middleware" or your application namespace |
4619
|
|
|
|
|
|
|
(the package name of your Catalyst application subclass), we also assume then |
4620
|
|
|
|
|
|
|
that it is a full namespace, and use it. |
4621
|
|
|
|
|
|
|
|
4622
|
|
|
|
|
|
|
(3) Lastly, we then assume that the scalar is a partial namespace, and attempt to |
4623
|
|
|
|
|
|
|
resolve it first by looking for it under your application namespace (for example |
4624
|
|
|
|
|
|
|
if you application is "MyApp::Web" and the scalar is "MyMiddleware", we'd look |
4625
|
|
|
|
|
|
|
under "MyApp::Web::Middleware::MyMiddleware") and if we don't find it there, we |
4626
|
|
|
|
|
|
|
will then look under the regular L<Plack::Middleware> namespace (i.e. for the |
4627
|
|
|
|
|
|
|
previous we'd try "Plack::Middleware::MyMiddleware"). We look under your application |
4628
|
|
|
|
|
|
|
namespace first to let you 'override' common L<Plack::Middleware> locally, should |
4629
|
|
|
|
|
|
|
you find that a good idea. |
4630
|
|
|
|
|
|
|
|
4631
|
|
|
|
|
|
|
Examples: |
4632
|
|
|
|
|
|
|
|
4633
|
|
|
|
|
|
|
package MyApp::Web; |
4634
|
|
|
|
|
|
|
|
4635
|
|
|
|
|
|
|
__PACKAGE__->config( |
4636
|
|
|
|
|
|
|
'psgi_middleware', [ |
4637
|
|
|
|
|
|
|
'Debug', ## MyAppWeb::Middleware::Debug->wrap or Plack::Middleware::Debug->wrap |
4638
|
|
|
|
|
|
|
'Plack::Middleware::Stacktrace', ## Plack::Middleware::Stacktrace->wrap |
4639
|
|
|
|
|
|
|
'+MyApp::Custom', ## MyApp::Custom->wrap |
4640
|
|
|
|
|
|
|
], |
4641
|
|
|
|
|
|
|
); |
4642
|
|
|
|
|
|
|
|
4643
|
|
|
|
|
|
|
=item a scalar followed by a hashref |
4644
|
|
|
|
|
|
|
|
4645
|
|
|
|
|
|
|
Just like the previous, except the following C<HashRef> is used as arguments |
4646
|
|
|
|
|
|
|
to initialize the middleware object. |
4647
|
|
|
|
|
|
|
|
4648
|
|
|
|
|
|
|
__PACKAGE__->config( |
4649
|
|
|
|
|
|
|
'psgi_middleware', [ |
4650
|
|
|
|
|
|
|
'Session' => {store => 'File'}, |
4651
|
|
|
|
|
|
|
]); |
4652
|
|
|
|
|
|
|
|
4653
|
|
|
|
|
|
|
=back |
4654
|
|
|
|
|
|
|
|
4655
|
|
|
|
|
|
|
Please see L<PSGI> for more on middleware. |
4656
|
|
|
|
|
|
|
|
4657
|
|
|
|
|
|
|
=head1 ENCODING |
4658
|
|
|
|
|
|
|
|
4659
|
|
|
|
|
|
|
Starting in L<Catalyst> version 5.90080 encoding is automatically enabled |
4660
|
|
|
|
|
|
|
and set to encode all body responses to UTF8 when possible and applicable. |
4661
|
|
|
|
|
|
|
Following is documentation on this process. If you are using an older |
4662
|
|
|
|
|
|
|
version of L<Catalyst> you should review documentation for that version since |
4663
|
|
|
|
|
|
|
a lot has changed. |
4664
|
|
|
|
|
|
|
|
4665
|
|
|
|
|
|
|
By default encoding is now 'UTF-8'. You may turn it off by setting |
4666
|
|
|
|
|
|
|
the encoding configuration to undef. |
4667
|
|
|
|
|
|
|
|
4668
|
|
|
|
|
|
|
MyApp->config(encoding => undef); |
4669
|
|
|
|
|
|
|
|
4670
|
|
|
|
|
|
|
This is recommended for temporary backwards compatibility only. |
4671
|
|
|
|
|
|
|
|
4672
|
|
|
|
|
|
|
To turn it off for a single request use the L<clear_encoding> |
4673
|
|
|
|
|
|
|
method to turn off encoding for this request. This can be useful |
4674
|
|
|
|
|
|
|
when you are setting the body to be an arbitrary block of bytes, |
4675
|
|
|
|
|
|
|
especially if that block happens to be a block of UTF8 text. |
4676
|
|
|
|
|
|
|
|
4677
|
|
|
|
|
|
|
Encoding is automatically applied when the content-type is set to |
4678
|
|
|
|
|
|
|
a type that can be encoded. Currently we encode when the content type |
4679
|
|
|
|
|
|
|
matches the following regular expression: |
4680
|
|
|
|
|
|
|
|
4681
|
|
|
|
|
|
|
$content_type =~ /^text|xml$|javascript$/ |
4682
|
|
|
|
|
|
|
|
4683
|
|
|
|
|
|
|
Encoding is set on the application, but it is copied to the context object |
4684
|
|
|
|
|
|
|
so that you can override it on a request basis. |
4685
|
|
|
|
|
|
|
|
4686
|
|
|
|
|
|
|
Be default we don't automatically encode 'application/json' since the most |
4687
|
|
|
|
|
|
|
common approaches to generating this type of response (Either via L<Catalyst::View::JSON> |
4688
|
|
|
|
|
|
|
or L<Catalyst::Action::REST>) will do so already and we want to avoid double |
4689
|
|
|
|
|
|
|
encoding issues. |
4690
|
|
|
|
|
|
|
|
4691
|
|
|
|
|
|
|
If you are producing JSON response in an unconventional manner (such |
4692
|
|
|
|
|
|
|
as via a template or manual strings) you should perform the UTF8 encoding |
4693
|
|
|
|
|
|
|
manually as well such as to conform to the JSON specification. |
4694
|
|
|
|
|
|
|
|
4695
|
|
|
|
|
|
|
NOTE: We also examine the value of $c->response->content_encoding. If |
4696
|
|
|
|
|
|
|
you set this (like for example 'gzip', and manually gzipping the body) |
4697
|
|
|
|
|
|
|
we assume that you have done all the necessary encoding yourself, since |
4698
|
|
|
|
|
|
|
we cannot encode the gzipped contents. If you use a plugin like |
4699
|
|
|
|
|
|
|
L<Catalyst::Plugin::Compress> you need to update to a modern version in order |
4700
|
|
|
|
|
|
|
to have this function correctly with the new UTF8 encoding code, or you |
4701
|
|
|
|
|
|
|
can use L<Plack::Middleware::Deflater> or (probably best) do your compression on |
4702
|
|
|
|
|
|
|
a front end proxy. |
4703
|
|
|
|
|
|
|
|
4704
|
|
|
|
|
|
|
=head2 Methods |
4705
|
|
|
|
|
|
|
|
4706
|
|
|
|
|
|
|
=over 4 |
4707
|
|
|
|
|
|
|
|
4708
|
|
|
|
|
|
|
=item encoding |
4709
|
|
|
|
|
|
|
|
4710
|
|
|
|
|
|
|
Returns an instance of an C<Encode> encoding |
4711
|
|
|
|
|
|
|
|
4712
|
|
|
|
|
|
|
print $c->encoding->name |
4713
|
|
|
|
|
|
|
|
4714
|
|
|
|
|
|
|
=item handle_unicode_encoding_exception ($exception_context) |
4715
|
|
|
|
|
|
|
|
4716
|
|
|
|
|
|
|
Method called when decoding process for a request fails. |
4717
|
|
|
|
|
|
|
|
4718
|
|
|
|
|
|
|
An C<$exception_context> hashref is provided to allow you to override the |
4719
|
|
|
|
|
|
|
behaviour of your application when given data with incorrect encodings. |
4720
|
|
|
|
|
|
|
|
4721
|
|
|
|
|
|
|
The default method throws exceptions in the case of invalid request parameters |
4722
|
|
|
|
|
|
|
(resulting in a 500 error), but ignores errors in upload filenames. |
4723
|
|
|
|
|
|
|
|
4724
|
|
|
|
|
|
|
The keys passed in the C<$exception_context> hash are: |
4725
|
|
|
|
|
|
|
|
4726
|
|
|
|
|
|
|
=over |
4727
|
|
|
|
|
|
|
|
4728
|
|
|
|
|
|
|
=item param_value |
4729
|
|
|
|
|
|
|
|
4730
|
|
|
|
|
|
|
The value which was not able to be decoded. |
4731
|
|
|
|
|
|
|
|
4732
|
|
|
|
|
|
|
=item error_msg |
4733
|
|
|
|
|
|
|
|
4734
|
|
|
|
|
|
|
The exception received from L<Encode>. |
4735
|
|
|
|
|
|
|
|
4736
|
|
|
|
|
|
|
=item encoding_step |
4737
|
|
|
|
|
|
|
|
4738
|
|
|
|
|
|
|
What type of data was being decoded. Valid values are (currently) |
4739
|
|
|
|
|
|
|
C<params> - for request parameters / arguments / captures |
4740
|
|
|
|
|
|
|
and C<uploads> - for request upload filenames. |
4741
|
|
|
|
|
|
|
|
4742
|
|
|
|
|
|
|
=back |
4743
|
|
|
|
|
|
|
|
4744
|
|
|
|
|
|
|
=back |
4745
|
|
|
|
|
|
|
|
4746
|
|
|
|
|
|
|
=head1 SUPPORT |
4747
|
|
|
|
|
|
|
|
4748
|
|
|
|
|
|
|
IRC: |
4749
|
|
|
|
|
|
|
|
4750
|
|
|
|
|
|
|
Join #catalyst on irc.perl.org. |
4751
|
|
|
|
|
|
|
|
4752
|
|
|
|
|
|
|
Mailing Lists: |
4753
|
|
|
|
|
|
|
|
4754
|
|
|
|
|
|
|
http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst |
4755
|
|
|
|
|
|
|
http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst-dev |
4756
|
|
|
|
|
|
|
|
4757
|
|
|
|
|
|
|
Web: |
4758
|
|
|
|
|
|
|
|
4759
|
|
|
|
|
|
|
http://catalyst.perl.org |
4760
|
|
|
|
|
|
|
|
4761
|
|
|
|
|
|
|
Wiki: |
4762
|
|
|
|
|
|
|
|
4763
|
|
|
|
|
|
|
http://dev.catalyst.perl.org |
4764
|
|
|
|
|
|
|
|
4765
|
|
|
|
|
|
|
=head1 SEE ALSO |
4766
|
|
|
|
|
|
|
|
4767
|
|
|
|
|
|
|
=head2 L<Task::Catalyst> - All you need to start with Catalyst |
4768
|
|
|
|
|
|
|
|
4769
|
|
|
|
|
|
|
=head2 L<Catalyst::Manual> - The Catalyst Manual |
4770
|
|
|
|
|
|
|
|
4771
|
|
|
|
|
|
|
=head2 L<Catalyst::Component>, L<Catalyst::Controller> - Base classes for components |
4772
|
|
|
|
|
|
|
|
4773
|
|
|
|
|
|
|
=head2 L<Catalyst::Engine> - Core engine |
4774
|
|
|
|
|
|
|
|
4775
|
|
|
|
|
|
|
=head2 L<Catalyst::Log> - Log class. |
4776
|
|
|
|
|
|
|
|
4777
|
|
|
|
|
|
|
=head2 L<Catalyst::Request> - Request object |
4778
|
|
|
|
|
|
|
|
4779
|
|
|
|
|
|
|
=head2 L<Catalyst::Response> - Response object |
4780
|
|
|
|
|
|
|
|
4781
|
|
|
|
|
|
|
=head2 L<Catalyst::Test> - The test suite. |
4782
|
|
|
|
|
|
|
|
4783
|
|
|
|
|
|
|
=head1 PROJECT FOUNDER |
4784
|
|
|
|
|
|
|
|
4785
|
|
|
|
|
|
|
sri: Sebastian Riedel <sri@cpan.org> |
4786
|
|
|
|
|
|
|
|
4787
|
|
|
|
|
|
|
=head1 CONTRIBUTORS |
4788
|
|
|
|
|
|
|
|
4789
|
|
|
|
|
|
|
abw: Andy Wardley |
4790
|
|
|
|
|
|
|
|
4791
|
|
|
|
|
|
|
acme: Leon Brocard <leon@astray.com> |
4792
|
|
|
|
|
|
|
|
4793
|
|
|
|
|
|
|
abraxxa: Alexander Hartmaier <abraxxa@cpan.org> |
4794
|
|
|
|
|
|
|
|
4795
|
|
|
|
|
|
|
andrewalker: André Walker <andre@cpan.org> |
4796
|
|
|
|
|
|
|
|
4797
|
|
|
|
|
|
|
Andrew Bramble |
4798
|
|
|
|
|
|
|
|
4799
|
|
|
|
|
|
|
Andrew Ford <A.Ford@ford-mason.co.uk> |
4800
|
|
|
|
|
|
|
|
4801
|
|
|
|
|
|
|
Andrew Ruthven |
4802
|
|
|
|
|
|
|
|
4803
|
|
|
|
|
|
|
andyg: Andy Grundman <andy@hybridized.org> |
4804
|
|
|
|
|
|
|
|
4805
|
|
|
|
|
|
|
audreyt: Audrey Tang |
4806
|
|
|
|
|
|
|
|
4807
|
|
|
|
|
|
|
bricas: Brian Cassidy <bricas@cpan.org> |
4808
|
|
|
|
|
|
|
|
4809
|
|
|
|
|
|
|
Caelum: Rafael Kitover <rkitover@io.com> |
4810
|
|
|
|
|
|
|
|
4811
|
|
|
|
|
|
|
chansen: Christian Hansen |
4812
|
|
|
|
|
|
|
|
4813
|
|
|
|
|
|
|
Chase Venters <chase.venters@gmail.com> |
4814
|
|
|
|
|
|
|
|
4815
|
|
|
|
|
|
|
chicks: Christopher Hicks |
4816
|
|
|
|
|
|
|
|
4817
|
|
|
|
|
|
|
Chisel Wright <pause@herlpacker.co.uk> |
4818
|
|
|
|
|
|
|
|
4819
|
|
|
|
|
|
|
Danijel Milicevic <me@danijel.de> |
4820
|
|
|
|
|
|
|
|
4821
|
|
|
|
|
|
|
davewood: David Schmidt <davewood@cpan.org> |
4822
|
|
|
|
|
|
|
|
4823
|
|
|
|
|
|
|
David Kamholz <dkamholz@cpan.org> |
4824
|
|
|
|
|
|
|
|
4825
|
|
|
|
|
|
|
David Naughton <naughton@umn.edu> |
4826
|
|
|
|
|
|
|
|
4827
|
|
|
|
|
|
|
David E. Wheeler |
4828
|
|
|
|
|
|
|
|
4829
|
|
|
|
|
|
|
dhoss: Devin Austin <dhoss@cpan.org> |
4830
|
|
|
|
|
|
|
|
4831
|
|
|
|
|
|
|
dkubb: Dan Kubb <dan.kubb-cpan@onautopilot.com> |
4832
|
|
|
|
|
|
|
|
4833
|
|
|
|
|
|
|
Drew Taylor |
4834
|
|
|
|
|
|
|
|
4835
|
|
|
|
|
|
|
dwc: Daniel Westermann-Clark <danieltwc@cpan.org> |
4836
|
|
|
|
|
|
|
|
4837
|
|
|
|
|
|
|
esskar: Sascha Kiefer |
4838
|
|
|
|
|
|
|
|
4839
|
|
|
|
|
|
|
fireartist: Carl Franks <cfranks@cpan.org> |
4840
|
|
|
|
|
|
|
|
4841
|
|
|
|
|
|
|
frew: Arthur Axel "fREW" Schmidt <frioux@gmail.com> |
4842
|
|
|
|
|
|
|
|
4843
|
|
|
|
|
|
|
gabb: Danijel Milicevic |
4844
|
|
|
|
|
|
|
|
4845
|
|
|
|
|
|
|
Gary Ashton Jones |
4846
|
|
|
|
|
|
|
|
4847
|
|
|
|
|
|
|
Gavin Henry <ghenry@perl.me.uk> |
4848
|
|
|
|
|
|
|
|
4849
|
|
|
|
|
|
|
Geoff Richards |
4850
|
|
|
|
|
|
|
|
4851
|
|
|
|
|
|
|
groditi: Guillermo Roditi <groditi@gmail.com> |
4852
|
|
|
|
|
|
|
|
4853
|
|
|
|
|
|
|
hobbs: Andrew Rodland <andrew@cleverdomain.org> |
4854
|
|
|
|
|
|
|
|
4855
|
|
|
|
|
|
|
ilmari: Dagfinn Ilmari Mannsåker <ilmari@ilmari.org> |
4856
|
|
|
|
|
|
|
|
4857
|
|
|
|
|
|
|
jcamacho: Juan Camacho |
4858
|
|
|
|
|
|
|
|
4859
|
|
|
|
|
|
|
jester: Jesse Sheidlower <jester@panix.com> |
4860
|
|
|
|
|
|
|
|
4861
|
|
|
|
|
|
|
jhannah: Jay Hannah <jay@jays.net> |
4862
|
|
|
|
|
|
|
|
4863
|
|
|
|
|
|
|
Jody Belka |
4864
|
|
|
|
|
|
|
|
4865
|
|
|
|
|
|
|
Johan Lindstrom |
4866
|
|
|
|
|
|
|
|
4867
|
|
|
|
|
|
|
jon: Jon Schutz <jjschutz@cpan.org> |
4868
|
|
|
|
|
|
|
|
4869
|
|
|
|
|
|
|
Jonathan Rockway <jrockway@cpan.org> |
4870
|
|
|
|
|
|
|
|
4871
|
|
|
|
|
|
|
Kieren Diment <kd@totaldatasolution.com> |
4872
|
|
|
|
|
|
|
|
4873
|
|
|
|
|
|
|
konobi: Scott McWhirter <konobi@cpan.org> |
4874
|
|
|
|
|
|
|
|
4875
|
|
|
|
|
|
|
marcus: Marcus Ramberg <mramberg@cpan.org> |
4876
|
|
|
|
|
|
|
|
4877
|
|
|
|
|
|
|
miyagawa: Tatsuhiko Miyagawa <miyagawa@bulknews.net> |
4878
|
|
|
|
|
|
|
|
4879
|
|
|
|
|
|
|
mgrimes: Mark Grimes <mgrimes@cpan.org> |
4880
|
|
|
|
|
|
|
|
4881
|
|
|
|
|
|
|
mst: Matt S. Trout <mst@shadowcatsystems.co.uk> |
4882
|
|
|
|
|
|
|
|
4883
|
|
|
|
|
|
|
mugwump: Sam Vilain |
4884
|
|
|
|
|
|
|
|
4885
|
|
|
|
|
|
|
naughton: David Naughton |
4886
|
|
|
|
|
|
|
|
4887
|
|
|
|
|
|
|
ningu: David Kamholz <dkamholz@cpan.org> |
4888
|
|
|
|
|
|
|
|
4889
|
|
|
|
|
|
|
nothingmuch: Yuval Kogman <nothingmuch@woobling.org> |
4890
|
|
|
|
|
|
|
|
4891
|
|
|
|
|
|
|
numa: Dan Sully <daniel@cpan.org> |
4892
|
|
|
|
|
|
|
|
4893
|
|
|
|
|
|
|
obra: Jesse Vincent |
4894
|
|
|
|
|
|
|
|
4895
|
|
|
|
|
|
|
Octavian Rasnita |
4896
|
|
|
|
|
|
|
|
4897
|
|
|
|
|
|
|
omega: Andreas Marienborg |
4898
|
|
|
|
|
|
|
|
4899
|
|
|
|
|
|
|
Oleg Kostyuk <cub.uanic@gmail.com> |
4900
|
|
|
|
|
|
|
|
4901
|
|
|
|
|
|
|
phaylon: Robert Sedlacek <phaylon@dunkelheit.at> |
4902
|
|
|
|
|
|
|
|
4903
|
|
|
|
|
|
|
rafl: Florian Ragwitz <rafl@debian.org> |
4904
|
|
|
|
|
|
|
|
4905
|
|
|
|
|
|
|
random: Roland Lammel <lammel@cpan.org> |
4906
|
|
|
|
|
|
|
|
4907
|
|
|
|
|
|
|
revmischa: Mischa Spiegelmock <revmischa@cpan.org> |
4908
|
|
|
|
|
|
|
|
4909
|
|
|
|
|
|
|
Robert Sedlacek <rs@474.at> |
4910
|
|
|
|
|
|
|
|
4911
|
|
|
|
|
|
|
rrwo: Robert Rothenberg <rrwo@cpan.org> |
4912
|
|
|
|
|
|
|
|
4913
|
|
|
|
|
|
|
SpiceMan: Marcel Montes |
4914
|
|
|
|
|
|
|
|
4915
|
|
|
|
|
|
|
sky: Arthur Bergman |
4916
|
|
|
|
|
|
|
|
4917
|
|
|
|
|
|
|
szbalint: Balint Szilakszi <szbalint@cpan.org> |
4918
|
|
|
|
|
|
|
|
4919
|
|
|
|
|
|
|
t0m: Tomas Doran <bobtfish@bobtfish.net> |
4920
|
|
|
|
|
|
|
|
4921
|
|
|
|
|
|
|
Ulf Edvinsson |
4922
|
|
|
|
|
|
|
|
4923
|
|
|
|
|
|
|
vanstyn: Henry Van Styn <vanstyn@cpan.org> |
4924
|
|
|
|
|
|
|
|
4925
|
|
|
|
|
|
|
Viljo Marrandi <vilts@yahoo.com> |
4926
|
|
|
|
|
|
|
|
4927
|
|
|
|
|
|
|
Will Hawes <info@whawes.co.uk> |
4928
|
|
|
|
|
|
|
|
4929
|
|
|
|
|
|
|
willert: Sebastian Willert <willert@cpan.org> |
4930
|
|
|
|
|
|
|
|
4931
|
|
|
|
|
|
|
wreis: Wallace Reis <wreis@cpan.org> |
4932
|
|
|
|
|
|
|
|
4933
|
|
|
|
|
|
|
Yuval Kogman <nothingmuch@woobling.org> |
4934
|
|
|
|
|
|
|
|
4935
|
|
|
|
|
|
|
rainboxx: Matthias Dietrich <perl@rainboxx.de> |
4936
|
|
|
|
|
|
|
|
4937
|
|
|
|
|
|
|
dd070: Dhaval Dhanani <dhaval070@gmail.com> |
4938
|
|
|
|
|
|
|
|
4939
|
|
|
|
|
|
|
Upasana <me@upasana.me> |
4940
|
|
|
|
|
|
|
|
4941
|
|
|
|
|
|
|
John Napiorkowski (jnap) <jjnapiork@cpan.org> |
4942
|
|
|
|
|
|
|
|
4943
|
|
|
|
|
|
|
=head1 COPYRIGHT |
4944
|
|
|
|
|
|
|
|
4945
|
|
|
|
|
|
|
Copyright (c) 2005-2015, the above named PROJECT FOUNDER and CONTRIBUTORS. |
4946
|
|
|
|
|
|
|
|
4947
|
|
|
|
|
|
|
=head1 LICENSE |
4948
|
|
|
|
|
|
|
|
4949
|
|
|
|
|
|
|
This library is free software. You can redistribute it and/or modify it under |
4950
|
|
|
|
|
|
|
the same terms as Perl itself. |
4951
|
|
|
|
|
|
|
|
4952
|
|
|
|
|
|
|
=cut |
4953
|
|
|
|
|
|
|
|
4954
|
|
|
|
|
|
|
no Moose; |
4955
|
|
|
|
|
|
|
|
4956
|
|
|
|
|
|
|
__PACKAGE__->meta->make_immutable; |
4957
|
|
|
|
|
|
|
|
4958
|
|
|
|
|
|
|
1; |