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