← Index
NYTProf Performance Profile   « line view »
For ./view
  Run on Fri Jul 31 18:42:36 2015
Reported on Fri Jul 31 18:48:15 2015

Filename/var/www/foswikidev/core/lib/Foswiki/Contrib/JsonRpcContrib/Server.pm
StatementsExecuted 34 statements in 1.37ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
1111.10ms1.31msFoswiki::Contrib::JsonRpcContrib::Server::::BEGIN@25Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@25
111614µs734µsFoswiki::Contrib::JsonRpcContrib::Server::::BEGIN@26Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@26
11116µs29µsFoswiki::Contrib::JsonRpcContrib::Server::::BEGIN@19Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@19
51116µs16µsFoswiki::Contrib::JsonRpcContrib::Server::::registerMethodFoswiki::Contrib::JsonRpcContrib::Server::registerMethod
11111µs11µsFoswiki::Contrib::JsonRpcContrib::Server::::newFoswiki::Contrib::JsonRpcContrib::Server::new
11110µs14µsFoswiki::Contrib::JsonRpcContrib::Server::::BEGIN@20Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@20
11110µs45µsFoswiki::Contrib::JsonRpcContrib::Server::::BEGIN@28Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@28
11110µs22µsFoswiki::Contrib::JsonRpcContrib::Server::::BEGIN@164Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@164
1119µs19µsFoswiki::Contrib::JsonRpcContrib::Server::::BEGIN@173Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@173
1119µs106µsFoswiki::Contrib::JsonRpcContrib::Server::::BEGIN@22Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@22
1114µs4µsFoswiki::Contrib::JsonRpcContrib::Server::::BEGIN@23Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@23
1114µs4µsFoswiki::Contrib::JsonRpcContrib::Server::::BEGIN@24Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@24
0000s0sFoswiki::Contrib::JsonRpcContrib::Server::::__ANON__[:174]Foswiki::Contrib::JsonRpcContrib::Server::__ANON__[:174]
0000s0sFoswiki::Contrib::JsonRpcContrib::Server::::__ANON__[:179]Foswiki::Contrib::JsonRpcContrib::Server::__ANON__[:179]
0000s0sFoswiki::Contrib::JsonRpcContrib::Server::::__ANON__[:184]Foswiki::Contrib::JsonRpcContrib::Server::__ANON__[:184]
0000s0sFoswiki::Contrib::JsonRpcContrib::Server::::__ANON__[:82]Foswiki::Contrib::JsonRpcContrib::Server::__ANON__[:82]
0000s0sFoswiki::Contrib::JsonRpcContrib::Server::::__ANON__[:90]Foswiki::Contrib::JsonRpcContrib::Server::__ANON__[:90]
0000s0sFoswiki::Contrib::JsonRpcContrib::Server::::dispatchFoswiki::Contrib::JsonRpcContrib::Server::dispatch
0000s0sFoswiki::Contrib::JsonRpcContrib::Server::::getHandlerFoswiki::Contrib::JsonRpcContrib::Server::getHandler
0000s0sFoswiki::Contrib::JsonRpcContrib::Server::::writeDebugFoswiki::Contrib::JsonRpcContrib::Server::writeDebug
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1# JSON-RPC for Foswiki
2#
3# Copyright (C) 2011-2015 Michael Daum http://michaeldaumconsulting.com
4#
5# This program is free software; you can redistribute it and/or
6# modify it under the terms of the GNU General Public License
7# as published by the Free Software Foundation; either version 2
8# of the License, or (at your option) any later version. For
9# more details read LICENSE in the root of this distribution.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14#
15# As per the GPL, removal of this notice is prohibited.
16
17package Foswiki::Contrib::JsonRpcContrib::Server;
18
19229µs241µs
# spent 29µs (16+13) within Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@19 which was called: # once (16µs+13µs) by Foswiki::Contrib::JsonRpcContrib::getServer at line 19
use strict;
# spent 29µs making 1 call to Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@19 # spent 13µs making 1 call to strict::import
20228µs218µs
# spent 14µs (10+4) within Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@20 which was called: # once (10µs+4µs) by Foswiki::Contrib::JsonRpcContrib::getServer at line 20
use warnings;
# spent 14µs making 1 call to Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@20 # spent 4µs making 1 call to warnings::import
21
22229µs2204µs
# spent 106µs (9+98) within Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@22 which was called: # once (9µs+98µs) by Foswiki::Contrib::JsonRpcContrib::getServer at line 22
use Error qw( :try );
# spent 106µs making 1 call to Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@22 # spent 98µs making 1 call to Error::import
23220µs14µs
# spent 4µs within Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@23 which was called: # once (4µs+0s) by Foswiki::Contrib::JsonRpcContrib::getServer at line 23
use Foswiki::Func ();
24219µs14µs
# spent 4µs within Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@24 which was called: # once (4µs+0s) by Foswiki::Contrib::JsonRpcContrib::getServer at line 24
use Foswiki::Contrib::JsonRpcContrib::Error ();
252101µs11.31ms
# spent 1.31ms (1.10+215µs) within Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@25 which was called: # once (1.10ms+215µs) by Foswiki::Contrib::JsonRpcContrib::getServer at line 25
use Foswiki::Contrib::JsonRpcContrib::Request ();
262103µs1734µs
# spent 734µs (614+120) within Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@26 which was called: # once (614µs+120µs) by Foswiki::Contrib::JsonRpcContrib::getServer at line 26
use Foswiki::Contrib::JsonRpcContrib::Response ();
# spent 734µs making 1 call to Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@26
27
282501µs280µs
# spent 45µs (10+35) within Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@28 which was called: # once (10µs+35µs) by Foswiki::Contrib::JsonRpcContrib::getServer at line 28
use constant TRACE => 0; # toggle me
# spent 45µs making 1 call to Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@28 # spent 35µs making 1 call to constant::import
29
30# Error codes for json-rpc response
31# -32700: Parse error - Invalid JSON was received by the server.
32# -32600: Invalid Request - The JSON sent is not a valid Request object.
33# -32601: Method not found - The method does not exist / is not available.
34# -32602: Invalid params - Invalid method parameter(s).
35# -32603: Internal error - Internal JSON-RPC error.
36# -32099 to -32000: Server error - Reserved for implementation-defined server-errors.
37# 0: ok
38# 1: unknown error
39# 401: access denied
40# 404: topic not found
41
42################################################################################
43# static
44sub writeDebug {
45 Foswiki::Func::writeDebug '- JsonRpcContrib::Server - ' . $_[0];
46}
47
48################################################################################
49# constructor
50
# spent 11µs within Foswiki::Contrib::JsonRpcContrib::Server::new which was called: # once (11µs+0s) by Foswiki::Contrib::JsonRpcContrib::getServer at line 42 of /var/www/foswikidev/core/lib/Foswiki/Contrib/JsonRpcContrib.pm
sub new {
511700ns my $class = shift;
52
5318µs my $this = bless( {}, $class );
54
5516µs return $this;
56}
57
58################################################################################
59
# spent 16µs within Foswiki::Contrib::JsonRpcContrib::Server::registerMethod which was called 5 times, avg 3µs/call: # 5 times (16µs+0s) by Foswiki::Contrib::JsonRpcContrib::registerMethod at line 31 of /var/www/foswikidev/core/lib/Foswiki/Contrib/JsonRpcContrib.pm, avg 3µs/call
sub registerMethod {
6054µs my ( $this, $namespace, $method, $fnref, $options ) = @_;
61
62 writeDebug("registerMethod($namespace, $method, $fnref)") if TRACE;
63
64518µs $this->{handler}{$namespace}{$method} = {
65 function => $fnref,
66 options => $options
67 };
68}
69
70################################################################################
71sub dispatch {
72 my ( $this, $session ) = @_;
73
74 writeDebug("called dispatch") if TRACE;
75
76 $Foswiki::Plugins::SESSION = $session;
77 $this->{session} = $session;
78
79 my $request;
80 try {
81 $request = new Foswiki::Contrib::JsonRpcContrib::Request($session);
82 }
83 catch Foswiki::Contrib::JsonRpcContrib::Error with {
84 my $error = shift;
85 Foswiki::Contrib::JsonRpcContrib::Response->print(
86 $session,
87 code => $error->{code},
88 message => $error->{message}
89 );
90 };
91 return unless defined $request;
92
93 # get topic parameter and set the location overriding any
94 # other value derived from the namespace param
95 my $topic = $request->param('topic')
96 || $Foswiki::cfg{HomeTopicName};
97 ( $session->{webName}, $session->{topicName} ) =
98 Foswiki::Func::normalizeWebTopicName( $Foswiki::cfg{UsersWebName},
99 $topic );
100 writeDebug("topic=$topic") if TRACE;
101
102 # get handler for this namespace
103 my $handler = $this->getHandler($request);
104 unless ( defined $handler ) {
105 Foswiki::Contrib::JsonRpcContrib::Response->print(
106 $session,
107 code => -32601,
108 message => "Invalid invocation - unknown handler for "
109 . $request->namespace() . "."
110 . $request->method(),
111 id => $request->id()
112 );
113 return;
114 }
115
116 # if there's login info, try and apply it
117 my $userName = $request->param('username');
118 if ($userName) {
119 writeDebug("checking password for $userName") if TRACE;
120 my $pass = $request->param('password') || '';
121 unless ( $session->{users}->checkPassword( $userName, $pass ) ) {
122 Foswiki::Contrib::JsonRpcContrib::Response->print(
123 $session,
124 code => 401,
125 message => "Access denied",
126 id => $request->id()
127 );
128 return;
129 }
130
131 my $cUID = $session->{users}->getCanonicalUserID($userName);
132 my $wikiName = $session->{users}->getWikiName($cUID);
133 $session->{users}->getLoginManager()
134 ->userLoggedIn( $userName, $wikiName );
135 }
136
137 # validate the request
138 if ( $handler->{validate} ) {
139 my $nonce = $request->param('validation_key');
140 if (
141 !defined($nonce)
142 || !Foswiki::Validation::isValidNonce(
143 $session->getCGISession(), $nonce
144 )
145 )
146 {
147 Foswiki::Contrib::JsonRpcContrib::Response->print(
148 $session,
149 code => -32600,
150 message => "Invalid validation code",
151 id => $request->id()
152 );
153 return;
154 }
155 }
156
157 Foswiki::Func::writeEvent( 'jsonrpc',
158 $request->namespace() . ' ' . $request->method() );
159
160 # call
161 my $code = 0;
162 my $result;
163 try {
164269µs234µs
# spent 22µs (10+12) within Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@164 which was called: # once (10µs+12µs) by Foswiki::Contrib::JsonRpcContrib::getServer at line 164
no strict 'refs';
# spent 22µs making 1 call to Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@164 # spent 12µs making 1 call to strict::unimport
165 my $function = $handler->{function};
166 writeDebug( "calling handler for "
167 . $request->namespace . "."
168 . $request->method )
169 if TRACE;
170 $result =
171 &$function( $session, $request, $session->{response},
172 $handler->{options} );
1732435µs228µs
# spent 19µs (9+9) within Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@173 which was called: # once (9µs+9µs) by Foswiki::Contrib::JsonRpcContrib::getServer at line 173
use strict 'refs';
# spent 19µs making 1 call to Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@173 # spent 10µs making 1 call to strict::import
174 }
175 catch Foswiki::Contrib::JsonRpcContrib::Error with {
176 my $error = shift;
177 $result = $error->{message};
178 $code = $error->{code};
179 }
180 catch Error::Simple with {
181 my $error = shift;
182 $result = $error->{-text};
183 $code = 1; # unknown error
184 };
185
186 # finally
187 my $redirectto = $request->param('redirectto');
188 if ( $code == 0 && defined $redirectto ) {
189 my $url;
190 if ( $redirectto =~ /^https?:/ ) {
191 $url = $redirectto;
192 }
193 else {
194 $url =
195 $session->getScriptUrl( 1, 'view', $session->{webName},
196 $redirectto );
197 }
198 $session->redirect($url);
199 }
200 else {
201 Foswiki::Contrib::JsonRpcContrib::Response->print(
202 $session,
203 code => $code,
204 message => $result,
205 id => $request->id()
206 );
207 }
208
209 return;
210}
211
212################################################################################
213sub getHandler {
214 my ( $this, $request ) = @_;
215
216 my $namespace = $request->namespace();
217 return unless $namespace;
218
219 my $method = $request->method();
220 return unless $method;
221
222 unless ( defined $this->{handler}{$namespace} ) {
223
224 # lazy register handler
225 if ( defined $Foswiki::cfg{JsonRpcContrib}{Handler}
226 && defined $Foswiki::cfg{JsonRpcContrib}{Handler}{$namespace}
227 && defined $Foswiki::cfg{JsonRpcContrib}{Handler}{$namespace}
228 {$method} )
229 {
230
231 my $def =
232 $Foswiki::cfg{JsonRpcContrib}{Handler}{$namespace}{$method};
233
234 writeDebug("compiling $def->{package} for $namespace.$method")
235 if TRACE;
236 eval qq(use $def->{package});
237
238 # disable on error
239 if ($@) {
240 print STDERR "JsonRPC handler compile error: $@\n";
241 $Foswiki::cfg{JsonRpcContrib}{Handler}{$namespace}{$method} =
242 undef;
243 return;
244 }
245
246 my $sub = $def->{package} . "::" . $def->{function};
247 $this->registerMethod( $namespace, $method, \&$sub,
248 $def->{options} );
249 }
250 }
251
252 return unless defined $this->{handler}{$namespace};
253
254 return $this->{handler}{$namespace}{$method};
255}
256
25712µs1;
258