| Filename | /appl/netdisco/perl5/lib/perl5/Dancer.pm |
| Statements | Executed 842 statements in 2.48ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 467 | 5 | 3 | 1.80ms | 3.92ms | Dancer::setting |
| 342 | 2 | 1 | 700µs | 1.06ms | Dancer::config |
| 33 | 1 | 1 | 192µs | 192µs | Dancer::debug |
| 0 | 0 | 0 | 0s | 0s | Dancer::BEGIN |
| 0 | 0 | 0 | 0s | 0s | Dancer::__ANON__[:466] |
| 0 | 0 | 0 | 0s | 0s | Dancer::__ANON__[:467] |
| 0 | 0 | 0 | 0s | 0s | Dancer::_init_script_dir |
| 0 | 0 | 0 | 0s | 0s | Dancer::_load_app |
| 0 | 0 | 0 | 0s | 0s | Dancer::_redirect |
| 0 | 0 | 0 | 0s | 0s | Dancer::_send_file |
| 0 | 0 | 0 | 0s | 0s | Dancer::_session |
| 0 | 0 | 0 | 0s | 0s | Dancer::_start |
| 0 | 0 | 0 | 0s | 0s | Dancer::after |
| 0 | 0 | 0 | 0s | 0s | Dancer::any |
| 0 | 0 | 0 | 0s | 0s | Dancer::before |
| 0 | 0 | 0 | 0s | 0s | Dancer::before_template |
| 0 | 0 | 0 | 0s | 0s | Dancer::captures |
| 0 | 0 | 0 | 0s | 0s | Dancer::content_type |
| 0 | 0 | 0 | 0s | 0s | Dancer::cookie |
| 0 | 0 | 0 | 0s | 0s | Dancer::cookies |
| 0 | 0 | 0 | 0s | 0s | Dancer::dance |
| 0 | 0 | 0 | 0s | 0s | Dancer::dancer_version |
| 0 | 0 | 0 | 0s | 0s | Dancer::del |
| 0 | 0 | 0 | 0s | 0s | Dancer::dirname |
| 0 | 0 | 0 | 0s | 0s | Dancer::engine |
| 0 | 0 | 0 | 0s | 0s | Dancer::error |
| 0 | 0 | 0 | 0s | 0s | Dancer::false |
| 0 | 0 | 0 | 0s | 0s | Dancer::forward |
| 0 | 0 | 0 | 0s | 0s | Dancer::from_dumper |
| 0 | 0 | 0 | 0s | 0s | Dancer::from_json |
| 0 | 0 | 0 | 0s | 0s | Dancer::from_xml |
| 0 | 0 | 0 | 0s | 0s | Dancer::from_yaml |
| 0 | 0 | 0 | 0s | 0s | Dancer::get |
| 0 | 0 | 0 | 0s | 0s | Dancer::halt |
| 0 | 0 | 0 | 0s | 0s | Dancer::header |
| 0 | 0 | 0 | 0s | 0s | Dancer::headers |
| 0 | 0 | 0 | 0s | 0s | Dancer::hook |
| 0 | 0 | 0 | 0s | 0s | Dancer::import |
| 0 | 0 | 0 | 0s | 0s | Dancer::info |
| 0 | 0 | 0 | 0s | 0s | Dancer::layout |
| 0 | 0 | 0 | 0s | 0s | Dancer::load |
| 0 | 0 | 0 | 0s | 0s | Dancer::load_app |
| 0 | 0 | 0 | 0s | 0s | Dancer::logger |
| 0 | 0 | 0 | 0s | 0s | Dancer::mime |
| 0 | 0 | 0 | 0s | 0s | Dancer::options |
| 0 | 0 | 0 | 0s | 0s | Dancer::param |
| 0 | 0 | 0 | 0s | 0s | Dancer::param_array |
| 0 | 0 | 0 | 0s | 0s | Dancer::params |
| 0 | 0 | 0 | 0s | 0s | Dancer::pass |
| 0 | 0 | 0 | 0s | 0s | Dancer::patch |
| 0 | 0 | 0 | 0s | 0s | Dancer::path |
| 0 | 0 | 0 | 0s | 0s | Dancer::post |
| 0 | 0 | 0 | 0s | 0s | Dancer::prefix |
| 0 | 0 | 0 | 0s | 0s | Dancer::push_header |
| 0 | 0 | 0 | 0s | 0s | Dancer::put |
| 0 | 0 | 0 | 0s | 0s | Dancer::redirect |
| 0 | 0 | 0 | 0s | 0s | Dancer::render_with_layout |
| 0 | 0 | 0 | 0s | 0s | Dancer::request |
| 0 | 0 | 0 | 0s | 0s | Dancer::send_error |
| 0 | 0 | 0 | 0s | 0s | Dancer::send_file |
| 0 | 0 | 0 | 0s | 0s | Dancer::session |
| 0 | 0 | 0 | 0s | 0s | Dancer::set |
| 0 | 0 | 0 | 0s | 0s | Dancer::set_cookie |
| 0 | 0 | 0 | 0s | 0s | Dancer::splat |
| 0 | 0 | 0 | 0s | 0s | Dancer::start |
| 0 | 0 | 0 | 0s | 0s | Dancer::status |
| 0 | 0 | 0 | 0s | 0s | Dancer::template |
| 0 | 0 | 0 | 0s | 0s | Dancer::to_dumper |
| 0 | 0 | 0 | 0s | 0s | Dancer::to_json |
| 0 | 0 | 0 | 0s | 0s | Dancer::to_xml |
| 0 | 0 | 0 | 0s | 0s | Dancer::to_yaml |
| 0 | 0 | 0 | 0s | 0s | Dancer::true |
| 0 | 0 | 0 | 0s | 0s | Dancer::upload |
| 0 | 0 | 0 | 0s | 0s | Dancer::uri_for |
| 0 | 0 | 0 | 0s | 0s | Dancer::var |
| 0 | 0 | 0 | 0s | 0s | Dancer::vars |
| 0 | 0 | 0 | 0s | 0s | Dancer::warning |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package Dancer; | ||||
| 2 | our $AUTHORITY = 'cpan:SUKRIA'; | ||||
| 3 | #ABSTRACT: lightweight yet powerful web application framework | ||||
| 4 | $Dancer::VERSION = '1.3512'; | ||||
| 5 | use strict; | ||||
| 6 | use warnings; | ||||
| 7 | use Carp; | ||||
| 8 | use Cwd 'realpath'; | ||||
| 9 | |||||
| 10 | use Dancer::App; | ||||
| 11 | use Dancer::Config; | ||||
| 12 | use Dancer::Cookies; | ||||
| 13 | use Dancer::FileUtils; | ||||
| 14 | use Dancer::GetOpt; | ||||
| 15 | use Dancer::Error; | ||||
| 16 | use Dancer::Hook; | ||||
| 17 | use Dancer::Logger; | ||||
| 18 | use Dancer::Renderer; | ||||
| 19 | use Dancer::Route; | ||||
| 20 | use Dancer::Serializer::JSON; | ||||
| 21 | use Dancer::Serializer::YAML; | ||||
| 22 | use Dancer::Serializer::XML; | ||||
| 23 | use Dancer::Serializer::Dumper; | ||||
| 24 | use Dancer::Session; | ||||
| 25 | use Dancer::SharedData; | ||||
| 26 | use Dancer::Handler; | ||||
| 27 | use Dancer::MIME; | ||||
| 28 | use Dancer::Exception qw(:all); | ||||
| 29 | |||||
| 30 | use Dancer::Continuation::Halted; | ||||
| 31 | use Dancer::Continuation::Route::Forwarded; | ||||
| 32 | use Dancer::Continuation::Route::Passed; | ||||
| 33 | use Dancer::Continuation::Route::ErrorSent; | ||||
| 34 | use Dancer::Continuation::Route::FileSent; | ||||
| 35 | use Dancer::Continuation::Route::Templated; | ||||
| 36 | |||||
| 37 | use File::Spec; | ||||
| 38 | use Scalar::Util; | ||||
| 39 | |||||
| 40 | use base 'Exporter'; | ||||
| 41 | |||||
| 42 | our @EXPORT = qw( | ||||
| 43 | after | ||||
| 44 | any | ||||
| 45 | before | ||||
| 46 | before_template | ||||
| 47 | cookie | ||||
| 48 | cookies | ||||
| 49 | config | ||||
| 50 | content_type | ||||
| 51 | dance | ||||
| 52 | dancer_version | ||||
| 53 | debug | ||||
| 54 | del | ||||
| 55 | dirname | ||||
| 56 | info | ||||
| 57 | error | ||||
| 58 | engine | ||||
| 59 | false | ||||
| 60 | forward | ||||
| 61 | from_dumper | ||||
| 62 | from_json | ||||
| 63 | from_yaml | ||||
| 64 | from_xml | ||||
| 65 | get | ||||
| 66 | halt | ||||
| 67 | header | ||||
| 68 | headers | ||||
| 69 | hook | ||||
| 70 | layout | ||||
| 71 | load | ||||
| 72 | load_app | ||||
| 73 | logger | ||||
| 74 | mime | ||||
| 75 | options | ||||
| 76 | param | ||||
| 77 | param_array | ||||
| 78 | params | ||||
| 79 | pass | ||||
| 80 | path | ||||
| 81 | patch | ||||
| 82 | post | ||||
| 83 | prefix | ||||
| 84 | push_header | ||||
| 85 | put | ||||
| 86 | redirect | ||||
| 87 | render_with_layout | ||||
| 88 | request | ||||
| 89 | send_file | ||||
| 90 | send_error | ||||
| 91 | set | ||||
| 92 | setting | ||||
| 93 | set_cookie | ||||
| 94 | session | ||||
| 95 | splat | ||||
| 96 | status | ||||
| 97 | start | ||||
| 98 | template | ||||
| 99 | to_dumper | ||||
| 100 | to_json | ||||
| 101 | to_yaml | ||||
| 102 | to_xml | ||||
| 103 | true | ||||
| 104 | upload | ||||
| 105 | captures | ||||
| 106 | uri_for | ||||
| 107 | var | ||||
| 108 | vars | ||||
| 109 | warning | ||||
| 110 | ); | ||||
| 111 | |||||
| 112 | # Dancer's syntax | ||||
| 113 | |||||
| 114 | sub after { | ||||
| 115 | Dancer::Deprecation->deprecated(reason => "use hooks!", | ||||
| 116 | version => '1.3080', | ||||
| 117 | fatal => 0); | ||||
| 118 | Dancer::Hook->new('after', @_); | ||||
| 119 | } | ||||
| 120 | sub before { | ||||
| 121 | Dancer::Deprecation->deprecated(reason => "use hooks!", | ||||
| 122 | version => '1.3080', | ||||
| 123 | fatal => 0); | ||||
| 124 | Dancer::Hook->new('before', @_); | ||||
| 125 | } | ||||
| 126 | sub before_template { | ||||
| 127 | Dancer::Deprecation->deprecated(reason => "use hooks!", | ||||
| 128 | version => '1.3080', | ||||
| 129 | fatal => 0); | ||||
| 130 | Dancer::Hook->new('before_template', @_); | ||||
| 131 | } | ||||
| 132 | |||||
| 133 | sub any { Dancer::App->current->registry->any_add(@_) } | ||||
| 134 | sub captures { Dancer::SharedData->request->params->{captures} } | ||||
| 135 | sub cookie { Dancer::Cookies->cookie( @_ ) } | ||||
| 136 | sub cookies { Dancer::Cookies->cookies } | ||||
| 137 | 342 | 758µs | 342 | 362µs | # spent 1.06ms (700µs+362µs) within Dancer::config which was called 342 times, avg 3µs/call:
# 171 times (431µs+247µs) by App::Netdisco::Util::Permission::check_acl_no at line 46 of App/Netdisco/Util/Permission.pm, avg 4µs/call
# 171 times (269µs+115µs) by App::Netdisco::Util::Permission::check_acl_only at line 69 of App/Netdisco/Util/Permission.pm, avg 2µs/call # spent 362µs making 342 calls to Dancer::Config::settings, avg 1µs/call |
| 138 | sub content_type { Dancer::SharedData->response->content_type(@_) } | ||||
| 139 | sub dance { goto &start } | ||||
| 140 | sub dancer_version { Dancer->VERSION } | ||||
| 141 | 33 | 177µs | 33 | 10.1ms | # spent 192µs within Dancer::debug which was called 33 times, avg 6µs/call:
# 33 times (192µs+0s) by App::Netdisco::Util::Device::_bail_msg at line 147 of App/Netdisco/Util/Device.pm, avg 6µs/call # spent 10.1ms making 33 calls to Dancer::Logger::debug, avg 307µs/call |
| 142 | sub del { Dancer::App->current->registry->universal_add('delete', @_) } | ||||
| 143 | sub dirname { Dancer::FileUtils::dirname(@_) } | ||||
| 144 | sub engine { Dancer::Engine->engine(@_) } | ||||
| 145 | sub error { goto &Dancer::Logger::error } | ||||
| 146 | sub false { 0 } | ||||
| 147 | sub forward { Dancer::SharedData->response->forward(@_); | ||||
| 148 | # throw a special continuation exception | ||||
| 149 | Dancer::Continuation::Route::Forwarded->new->throw; | ||||
| 150 | } | ||||
| 151 | sub from_dumper { Dancer::Serializer::Dumper::from_dumper(@_) } | ||||
| 152 | sub from_json { Dancer::Serializer::JSON::from_json(@_) } | ||||
| 153 | sub from_xml { Dancer::Serializer::XML::from_xml(@_) } | ||||
| 154 | sub from_yaml { Dancer::Serializer::YAML::from_yaml(@_) } | ||||
| 155 | sub get { map { my $r = $_; Dancer::App->current->registry->universal_add($r, @_) } qw(head get) } | ||||
| 156 | sub halt { Dancer::SharedData->response->halt(@_); | ||||
| 157 | # throw a special continuation exception | ||||
| 158 | Dancer::Continuation::Halted->new->throw; | ||||
| 159 | } | ||||
| 160 | sub header { goto &headers } | ||||
| 161 | sub info { goto &Dancer::Logger::info } | ||||
| 162 | sub push_header { Dancer::SharedData->response->push_header(@_); } | ||||
| 163 | sub headers { Dancer::SharedData->response->headers(@_); } | ||||
| 164 | sub hook { Dancer::Hook->new(@_) } | ||||
| 165 | sub layout { | ||||
| 166 | Dancer::Deprecation->deprecated(reason => "use 'set layout => \"value\"'", | ||||
| 167 | version => '1.3050', | ||||
| 168 | fatal => 1); | ||||
| 169 | } | ||||
| 170 | sub load { require $_ for @_ } | ||||
| 171 | sub load_app { goto &_load_app } # goto doesn't add a call frame. So caller() will work as expected | ||||
| 172 | sub logger { | ||||
| 173 | Dancer::Deprecation->deprecated(reason => "use 'set logger => \"value\"'", | ||||
| 174 | fatal => 1,version=>'1.3050'); | ||||
| 175 | } | ||||
| 176 | sub mime { Dancer::MIME->instance() } | ||||
| 177 | sub options { Dancer::App->current->registry->universal_add('options', @_) } | ||||
| 178 | sub params { Dancer::SharedData->request->params(@_) } | ||||
| 179 | sub param { params->{$_[0]} } | ||||
| 180 | sub param_array { | ||||
| 181 | my $value = param(shift); | ||||
| 182 | |||||
| 183 | my @array = ref $value eq 'ARRAY' ? @$value | ||||
| 184 | : defined $value ? ( $value ) | ||||
| 185 | : () | ||||
| 186 | ; | ||||
| 187 | |||||
| 188 | return @array; | ||||
| 189 | } | ||||
| 190 | sub pass { Dancer::SharedData->response->pass(1); | ||||
| 191 | # throw a special continuation exception | ||||
| 192 | Dancer::Continuation::Route::Passed->new->throw; | ||||
| 193 | } | ||||
| 194 | sub patch { Dancer::App->current->registry->universal_add('patch', @_) } | ||||
| 195 | sub path { Dancer::FileUtils::path(@_) } | ||||
| 196 | sub post { Dancer::App->current->registry->universal_add('post', @_) } | ||||
| 197 | sub prefix { @_ == 0 ? Dancer::App->current->get_prefix : | ||||
| 198 | Dancer::App->current->set_prefix(@_) } | ||||
| 199 | sub put { Dancer::App->current->registry->universal_add('put', @_) } | ||||
| 200 | sub redirect { goto &_redirect } | ||||
| 201 | sub render_with_layout { Dancer::Template::Abstract->_render_with_layout(@_) } | ||||
| 202 | sub request { Dancer::SharedData->request } | ||||
| 203 | sub send_error { Dancer::Continuation::Route::ErrorSent->new( | ||||
| 204 | return_value => Dancer::Error->new( | ||||
| 205 | message => $_[0], | ||||
| 206 | code => $_[1] || 500)->render() | ||||
| 207 | )->throw } | ||||
| 208 | #sub send_file { goto &_send_file } | ||||
| 209 | sub send_file { Dancer::Continuation::Route::FileSent->new( | ||||
| 210 | return_value => _send_file(@_) | ||||
| 211 | )->throw | ||||
| 212 | } | ||||
| 213 | sub set { goto &setting } | ||||
| 214 | sub set_cookie { Dancer::Cookies->set_cookie(@_) } | ||||
| 215 | 467 | 1.54ms | 934 | 2.11ms | # spent 3.92ms (1.80+2.11) within Dancer::setting which was called 467 times, avg 8µs/call:
# 171 times (687µs+792µs) by App::Netdisco::Util::Permission::check_acl_no at line 46 of App/Netdisco/Util/Permission.pm, avg 9µs/call
# 171 times (541µs+654µs) by App::Netdisco::Util::Permission::check_acl_only at line 69 of App/Netdisco/Util/Permission.pm, avg 7µs/call
# 57 times (346µs+413µs) by App::Netdisco::Util::Device::is_discoverable at line 174 of App/Netdisco/Util/Device.pm, avg 13µs/call
# 57 times (125µs+176µs) by App::Netdisco::Util::Device::is_discoverable at line 179 of App/Netdisco/Util/Device.pm, avg 5µs/call
# 11 times (104µs+78µs) by App::Netdisco::JobQueue::PostgreSQL::_get_denied_actions at line 37 of App/Netdisco/JobQueue/PostgreSQL.pm, avg 16µs/call # spent 1.62ms making 467 calls to Dancer::Config::setting, avg 3µs/call
# spent 488µs making 467 calls to Dancer::App::applications, avg 1µs/call |
| 216 | sub session { goto &_session } | ||||
| 217 | sub splat { @{ Dancer::SharedData->request->params->{splat} || [] } } | ||||
| 218 | sub start { goto &_start } | ||||
| 219 | sub status { Dancer::SharedData->response->status(@_) } | ||||
| 220 | sub template { Dancer::Template::Abstract->template(@_) } | ||||
| 221 | sub to_dumper { Dancer::Serializer::Dumper::to_dumper(@_) } | ||||
| 222 | sub to_json { Dancer::Serializer::JSON::to_json(@_) } | ||||
| 223 | sub to_xml { Dancer::Serializer::XML::to_xml(@_) } | ||||
| 224 | sub to_yaml { Dancer::Serializer::YAML::to_yaml(@_) } | ||||
| 225 | sub true { 1 } | ||||
| 226 | sub upload { Dancer::SharedData->request->upload(@_) } | ||||
| 227 | sub uri_for { Dancer::SharedData->request->uri_for(@_) } | ||||
| 228 | sub var { Dancer::SharedData->var(@_) } | ||||
| 229 | sub vars { Dancer::SharedData->vars } | ||||
| 230 | sub warning { goto &Dancer::Logger::warning } | ||||
| 231 | |||||
| 232 | # When importing the package, strict and warnings pragma are loaded, | ||||
| 233 | # and the appdir detection is performed. | ||||
| 234 | { | ||||
| 235 | my $as_script = 0; | ||||
| 236 | |||||
| 237 | sub import { | ||||
| 238 | my ($class, @args) = @_; | ||||
| 239 | my ($package, $script) = caller; | ||||
| 240 | |||||
| 241 | strict->import; | ||||
| 242 | warnings->import; | ||||
| 243 | utf8->import; | ||||
| 244 | |||||
| 245 | my @final_args; | ||||
| 246 | my $syntax_only = 0; | ||||
| 247 | foreach (@args) { | ||||
| 248 | if ( $_ eq ':moose' ) { | ||||
| 249 | push @final_args, '!before', '!after'; | ||||
| 250 | } | ||||
| 251 | elsif ( $_ eq ':tests' ) { | ||||
| 252 | push @final_args, '!pass'; | ||||
| 253 | } | ||||
| 254 | elsif ( $_ eq ':syntax' ) { | ||||
| 255 | $syntax_only = 1; | ||||
| 256 | } | ||||
| 257 | elsif ($_ eq ':script') { | ||||
| 258 | $as_script = 1; | ||||
| 259 | } else { | ||||
| 260 | push @final_args, $_; | ||||
| 261 | } | ||||
| 262 | } | ||||
| 263 | |||||
| 264 | $class->export_to_level(1, $class, @final_args); | ||||
| 265 | |||||
| 266 | # if :syntax option exists, don't change settings | ||||
| 267 | return if $syntax_only; | ||||
| 268 | |||||
| 269 | $as_script = 1 if $ENV{PLACK_ENV}; | ||||
| 270 | |||||
| 271 | Dancer::GetOpt->process_args unless $as_script; | ||||
| 272 | |||||
| 273 | _init_script_dir($script); | ||||
| 274 | Dancer::Config->load; | ||||
| 275 | } | ||||
| 276 | |||||
| 277 | } | ||||
| 278 | |||||
| 279 | # private code | ||||
| 280 | |||||
| 281 | # FIXME handle previous usage of load_app with multiple app names | ||||
| 282 | sub _load_app { | ||||
| 283 | my ($app_name, %options) = @_; | ||||
| 284 | my $script = (caller)[1]; | ||||
| 285 | Dancer::Logger::core("loading application $app_name"); | ||||
| 286 | |||||
| 287 | # set the application | ||||
| 288 | my $app = Dancer::App->set_running_app($app_name); | ||||
| 289 | |||||
| 290 | # Application options | ||||
| 291 | $app->set_app_prefix($options{prefix}) if $options{prefix}; | ||||
| 292 | $app->settings($options{settings}) if $options{settings}; | ||||
| 293 | |||||
| 294 | # load the application | ||||
| 295 | _init_script_dir($script); | ||||
| 296 | my ($res, $error) = Dancer::ModuleLoader->load($app_name); | ||||
| 297 | $res or raise core => "unable to load application $app_name : $error"; | ||||
| 298 | |||||
| 299 | # restore the main application | ||||
| 300 | Dancer::App->set_running_app('main'); | ||||
| 301 | } | ||||
| 302 | |||||
| 303 | sub _init_script_dir { | ||||
| 304 | my ($script) = @_; | ||||
| 305 | |||||
| 306 | my ($script_vol, $script_dirs, $script_name) = | ||||
| 307 | File::Spec->splitpath(File::Spec->rel2abs($script)); | ||||
| 308 | |||||
| 309 | # normalize | ||||
| 310 | if ( -d ( my $fulldir = File::Spec->catdir( $script_dirs, $script_name ) ) ) { | ||||
| 311 | $script_dirs = $fulldir; | ||||
| 312 | $script_name = ''; | ||||
| 313 | } | ||||
| 314 | |||||
| 315 | my @script_dirs = File::Spec->splitdir($script_dirs); | ||||
| 316 | my $script_path; | ||||
| 317 | if ($script_vol) { | ||||
| 318 | $script_path = Dancer::path($script_vol, $script_dirs); | ||||
| 319 | } else { | ||||
| 320 | $script_path = Dancer::path($script_dirs); | ||||
| 321 | } | ||||
| 322 | |||||
| 323 | my $LAYOUT_PRE_DANCER_1_2 = 1; | ||||
| 324 | |||||
| 325 | # in bin/ or public/ or t/ we need to go one level up to find the appdir | ||||
| 326 | $LAYOUT_PRE_DANCER_1_2 = 0 | ||||
| 327 | if ($script_dirs[$#script_dirs - 1] eq 'bin') | ||||
| 328 | or ($script_dirs[$#script_dirs - 1] eq 'public') | ||||
| 329 | or ($script_dirs[$#script_dirs - 1] eq 't'); | ||||
| 330 | |||||
| 331 | my $appdir = $ENV{DANCER_APPDIR} || ( | ||||
| 332 | $LAYOUT_PRE_DANCER_1_2 | ||||
| 333 | ? $script_path | ||||
| 334 | : File::Spec->rel2abs(Dancer::path($script_path, '..')) | ||||
| 335 | ); | ||||
| 336 | Dancer::setting(appdir => $appdir); | ||||
| 337 | |||||
| 338 | # once the dancer_appdir have been defined, we export to env | ||||
| 339 | $ENV{DANCER_APPDIR} = $appdir; | ||||
| 340 | |||||
| 341 | Dancer::Logger::core("initializing appdir to: `$appdir'"); | ||||
| 342 | |||||
| 343 | Dancer::setting(confdir => $ENV{DANCER_CONFDIR} | ||||
| 344 | || $appdir) unless Dancer::setting('confdir'); | ||||
| 345 | |||||
| 346 | Dancer::setting(public => $ENV{DANCER_PUBLIC} | ||||
| 347 | || Dancer::FileUtils::path($appdir, 'public')); | ||||
| 348 | |||||
| 349 | Dancer::setting(views => $ENV{DANCER_VIEWS} | ||||
| 350 | || Dancer::FileUtils::path($appdir, 'views')); | ||||
| 351 | |||||
| 352 | my ($res, $error) = Dancer::ModuleLoader->use_lib(Dancer::FileUtils::path($appdir, 'lib')); | ||||
| 353 | $res or raise core => "unable to set libdir : $error"; | ||||
| 354 | } | ||||
| 355 | |||||
| 356 | |||||
| 357 | # Scheme grammar as defined in RFC 2396 | ||||
| 358 | # scheme = alpha *( alpha | digit | "+" | "-" | "." ) | ||||
| 359 | my $scheme_re = qr{ [a-z][a-z0-9\+\-\.]* }ix; | ||||
| 360 | sub _redirect { | ||||
| 361 | my ($destination, $status) = @_; | ||||
| 362 | |||||
| 363 | # RFC 2616 requires an absolute URI with a scheme, | ||||
| 364 | # turn the URI into that if it needs it | ||||
| 365 | if ($destination !~ m{^ $scheme_re : }x) { | ||||
| 366 | my $request = Dancer::SharedData->request; | ||||
| 367 | $destination = $request->uri_for($destination, {}, 1); | ||||
| 368 | } | ||||
| 369 | my $response = Dancer::SharedData->response; | ||||
| 370 | $response->status($status || 302); | ||||
| 371 | $response->headers('Location' => $destination); | ||||
| 372 | } | ||||
| 373 | |||||
| 374 | sub _session { | ||||
| 375 | engine 'session' | ||||
| 376 | or raise core => "Must specify session engine in settings prior to using 'session' keyword"; | ||||
| 377 | @_ == 0 ? Dancer::Session->get | ||||
| 378 | : @_ == 1 ? Dancer::Session->read(@_) | ||||
| 379 | : Dancer::Session->write(@_); | ||||
| 380 | } | ||||
| 381 | |||||
| 382 | sub _send_file { | ||||
| 383 | my ($path, %options) = @_; | ||||
| 384 | my $env = Dancer::SharedData->request->env; | ||||
| 385 | |||||
| 386 | my $request = Dancer::Request->new_for_request('GET' => $path); | ||||
| 387 | Dancer::SharedData->request($request); | ||||
| 388 | |||||
| 389 | # if you asked for streaming but it's not supported in PSGI | ||||
| 390 | if ( $options{'streaming'} && ! $env->{'psgi.streaming'} ) { | ||||
| 391 | # TODO: throw a fit (AKA "exception") or a Dancer::Error? | ||||
| 392 | raise core => 'Sorry, streaming is not supported on this server.'; | ||||
| 393 | } | ||||
| 394 | |||||
| 395 | if (exists($options{content_type})) { | ||||
| 396 | $request->content_type($options{content_type}); | ||||
| 397 | } | ||||
| 398 | |||||
| 399 | # If we're given an IO::Scalar object, DTRT (take the scalar ref from it) | ||||
| 400 | if (Scalar::Util::blessed($path) && $path->isa('IO::Scalar')) { | ||||
| 401 | $path = $path->sref; | ||||
| 402 | } | ||||
| 403 | |||||
| 404 | my $resp; | ||||
| 405 | if (ref($path) eq "SCALAR") { | ||||
| 406 | # send_data | ||||
| 407 | $resp = Dancer::SharedData->response() || Dancer::Response->new(); | ||||
| 408 | $resp->header('Content-Type' => exists($options{content_type}) ? | ||||
| 409 | $options{content_type} : Dancer::MIME->default()); | ||||
| 410 | $resp->content($$path); | ||||
| 411 | } else { | ||||
| 412 | # real send_file | ||||
| 413 | if ($options{system_path} && -f $path) { | ||||
| 414 | $resp = Dancer::Renderer->get_file_response_for_path($path); | ||||
| 415 | } else { | ||||
| 416 | $resp = Dancer::Renderer->get_file_response(); | ||||
| 417 | } | ||||
| 418 | } | ||||
| 419 | |||||
| 420 | if ($resp) { | ||||
| 421 | |||||
| 422 | if (exists($options{filename})) { | ||||
| 423 | $resp->push_header('Content-Disposition' => | ||||
| 424 | "attachment; filename=\"$options{filename}\"" | ||||
| 425 | ); | ||||
| 426 | } | ||||
| 427 | |||||
| 428 | if ( $options{'streaming'} ) { | ||||
| 429 | # handle streaming | ||||
| 430 | $resp->streamed( sub { | ||||
| 431 | my ( $status, $headers ) = @_; | ||||
| 432 | my %callbacks = defined $options{'callbacks'} ? | ||||
| 433 | %{ $options{'callbacks'} } : | ||||
| 434 | (); | ||||
| 435 | |||||
| 436 | return sub { | ||||
| 437 | my $respond = shift; | ||||
| 438 | exists $callbacks{'override'} | ||||
| 439 | and return $callbacks{'override'}->( $respond, $resp ); | ||||
| 440 | |||||
| 441 | # get respond callback and set headers, get writer in return | ||||
| 442 | my $writer = $respond->( [ | ||||
| 443 | $status, | ||||
| 444 | $headers, | ||||
| 445 | ] ); | ||||
| 446 | |||||
| 447 | # get content from original response | ||||
| 448 | my $content = $resp->content; | ||||
| 449 | |||||
| 450 | exists $callbacks{'around'} | ||||
| 451 | and return $callbacks{'around'}->( $writer, $content ); | ||||
| 452 | |||||
| 453 | if ( ref $content ) { | ||||
| 454 | my $bytes = $options{'bytes'} || '43008'; # 42K (dams) | ||||
| 455 | my $buf; | ||||
| 456 | while ( ( my $read = sysread $content, $buf, $bytes ) != 0 ) { | ||||
| 457 | if ( exists $callbacks{'around_content'} ) { | ||||
| 458 | $callbacks{'around_content'}->( $writer, $buf ); | ||||
| 459 | } else { | ||||
| 460 | $writer->write($buf); | ||||
| 461 | } | ||||
| 462 | } | ||||
| 463 | } else { | ||||
| 464 | $writer->write($content); | ||||
| 465 | } | ||||
| 466 | }; | ||||
| 467 | } ); | ||||
| 468 | } | ||||
| 469 | |||||
| 470 | return $resp; | ||||
| 471 | |||||
| 472 | } | ||||
| 473 | |||||
| 474 | Dancer::Error->new( | ||||
| 475 | code => 404, | ||||
| 476 | message => "No such file: `$path'" | ||||
| 477 | )->render(); | ||||
| 478 | } | ||||
| 479 | |||||
| 480 | # Start/Run the application with the chosen apphandler | ||||
| 481 | sub _start { | ||||
| 482 | my ($class, $request) = @_; | ||||
| 483 | Dancer::Config->load; | ||||
| 484 | |||||
| 485 | # Backward compatibility for app.psgi that has sub { Dancer->dance($req) } | ||||
| 486 | if ($request) { | ||||
| 487 | Dancer::Handler->init_request_headers( $request->env ); | ||||
| 488 | # TODO _build_headers should either not be private, or we should call | ||||
| 489 | # init | ||||
| 490 | $request->_build_headers; | ||||
| 491 | return Dancer::Handler->handle_request($request); | ||||
| 492 | } | ||||
| 493 | |||||
| 494 | my $handler = Dancer::Handler->get_handler; | ||||
| 495 | Dancer::Logger::core("loading handler '".ref($handler)."'"); | ||||
| 496 | return $handler->dance; | ||||
| 497 | } | ||||
| 498 | |||||
| 499 | |||||
| 500 | 1; | ||||
| 501 | |||||
| 502 | __END__ |