-
Notifications
You must be signed in to change notification settings - Fork 38
/
JsonRpcContrib.txt
262 lines (220 loc) · 10.1 KB
/
JsonRpcContrib.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
%META:TOPICINFO{author="ProjectContributor" comment="" date="1454519814" format="1.1" version="1"}%
---+!! %TOPIC%
%SHORTDESCRIPTION%
%TOC%
---++ Summary
This package implements a [[http://en.wikipedia.org/wiki/JSON-RPC][JSON-RPC 2.0]] protocol to interface
with Foswiki and its plugins.
In contrast to the normal REST interface of Foswiki, a JSON-RPC interface
offers well defined calling semantics for requests and responses. The
interface will also take care that any received data is recoded
to the server's character encoding. JSON-RPC is normally called as part of
some !JavaScript AJAX application.
<nop>%TOPIC% also comes with a jQuery plugin to simplify working with
JSON-RPC. This is a simple wrapper around jQuery's own
AJAX capabilities.
---++ Registering JSON-RPC procedures
Foswiki plugins are able to register their own handler for a specific
method in a given namespace, thus:
<verbatim>
use Foswiki::Contrib::JsonRpcContrib ();
sub initPlugin {
...
Foswiki::Contrib::JsonRpcContrib::registerMethod(
"MyNamespace",
"someMethod",
\$jsonRpcSomeMethod
);
...
}
# Plugin's implementation
sub jsonRpcSomeMethod {
my ($session, $request) = @_;
...
# Return some result
return $result;
}
</verbatim>
---++ Handler functions
The handler function in your plugin takes two parameters, =$session= and =$request=. =$session= is a reference to the Foswiki session; most implementers should simply ignore this. =$request= is a reference to the JSON request object. The following methods are available on this object:
* =param('param1')= - returns the value of a single named parameter
* =params()= - returns a reference to the entire parameter hash
* =method()= - returns the method
* =namespace()= - returns the namespace
The handler function can return a scalar or a reference to an acyclic graph (a tree structure). The structure may contain blessed data (perl objects) if (and only if) those objects implement the =TO_JSON= method described in the documentation for the CPAN JSON module.
Errors can be signalled using a simple =die=. Such errors will be returned to the caller with an =errorCode= of 1. If you need to pass back extended error information, you will have to encode it in the =die= message.
---++ Calling using a POST
Once a handler is registered it may be called using an URL of the format:
=%SCRIPTURL{"jsonrpc"}%/MyNamespace=
... while POSTing a JSON-encoded request according to the JSON-RPC 2.0 specification,
like,
<verbatim>
{
jsonrpc: "2.0",
method: "someMethod",
params: {
topic: "Web.Topic",
...
param1: "value1",
param2: "value2",
...
},
id: "caller's id"
}
</verbatim>
---++ Calling using jQuery
The jQuery plugin can be used by requesting it via
=%<nop>JQREQUIRE{"jsonrpc"}%=. JSON-RPC can now be called like this:
<verbatim>
$.jsonRpc(
endpoint, /* %SCRIPTURL{"jsonrpc"}% */
{
namespace: "MyNamespace",
method: "someMethod",
id: "some caller's id",
params: {
topic: "Web.Topic",
...
param1: "value1",
param2: "value2",
},
beforeSend: function(xhr) { ... },
error: function(jsonResponse, textStatus, xhr) { ... },
success: function(jsonResponse, textStatus, xhr) { ... }
}
);
</verbatim>
---++ Error response
If the procedure fails for any reason the JSON response will have the format
<verbatim>
{
jsonrpc: "2.0",
error: {
code: errorCode,
message: "error description"
},
id: "caller's id"
}
</verbatim>
The following error codes are defined:
* -32700: Parse error - Invalid JSON was received by the server.
* -32600: Invalid Request - The JSON sent is not a valid Request object.
* -32601: Method not found - The method does not exist / is not available.
* -32602: Invalid params - Invalid method parameter(s).
* -32603: Internal error - Internal JSON-RPC error.
* -32099 to -32000: Server error - Reserved for implementation-defined server-errors.
* 1: unknown error - a =die= in the handler will return this
* 401: access denied - returned if provided credentials are incorrect
---++ Success response
If the call is successful the JSON response will be of the format:
<verbatim>
{
jsonrpc: "2.0",
result: some-result-object,
id: "caller's id"
}
</verbatim>
---++ Authentication
If there is an existing login session then JSON-RPC calls will be authenticated using that session. Alternatively, requests can be authenticated by passing in =username= and =password= URL parameters. It is strongly recommended that this is only done if the communications links is secure (https:), as these parameters are sent in plain text.
---++ Extensions to the standard
JSON-RPC 2.0 normally only allows you to pass parameters to a remote
procedure using a well formed request object as described
above. However in real-live web applications, data to be transmitted to
a specific endpoint is most conveniently sent using URL parameters (as is
the case for normal HTML forms).
Instead of requiring all form fields to be converted into a
JSON-RPC request object on the client side, the JsonRpcContrib
converts form data to a proper request object transparently.
This way you can call a JSON-RPC function using a simple form submission
from the client.
The called namespace and method can thus be specified much like a
subject/verb url to a REST interface. These calls are equivalent:
<verbatim>
$.jsonRpc(
"%SCRIPTURL{"jsonrpc"}%"
namespace: "MyNamespace",
method: "someMethod",
...
);
</verbatim>
<verbatim>
$.jsonRpc(
"%SCRIPTURL{"jsonrpc"}%/MyNamespace",
method: "someMethod",
...
);
</verbatim>
<verbatim>
$.jsonRpc(
"%SCRIPTURL{"jsonrpc"}%/MyNamespace/someMethod"
...
);
</verbatim>
You can also use an HTML form:
<verbatim>
<form action="%SCRIPTURL{"jsonrpc"}%" method="post">
<input type="hidden" name="namespace" value="MyNamespace" />
<input type="hidden" name="method" value="someMethod" />
...
</form>
</verbatim>
<verbatim>
<form action="%SCRIPTURL{"jsonrpc"}%/Mynamespace" method="post">
<input type="hidden" name="method" value="someMethod" />
...
</form>
</verbatim>
<verbatim>
<form action="%SCRIPTURL{"jsonrpc"}%/Mynamespace/someMethod" method="post">
...
</form>
</verbatim>
Forms of this type can easily be sent to the server using %SYSTEMWEB%.JQueryForm's =$.ajaxSubmit()= method.
If a namespace, method, or parameters are specified as part of a JSON-RPC request object as well as using URL parameters, the URL parameters take higher precedence and are merged into the request object.
---++ Installation Instructions
%$INSTALL_INSTRUCTIONS%
---++ Info
<!--
* Set SHORTDESCRIPTION = %$SHORTDESCRIPTION%
-->
| Change History: | <!-- versions below in reverse order --> |
| 03 Feb 2016: (2.24) | Foswikitask:Item13405: Add NFC normalization of Unicode strings. |
| 14 Jul 2015: (2.23) | fixed encoding of compressed responses Foswikitask:Item13521 |
| 14 Jun 2015: (2.22) | Release with Foswiki 2.0.<br />\
Foswikitask:Item13378: Implement UNICODE support,<br />\
Foswikitask:Item13323: Use /usr/bin/env perl.<br />\
Foswikitask:Item13412: Don't utf-8 encode response |
| 29 Jan 2015: | Foswikitask:Item13238: fix content-type of response |
| 17 Dec 2014: | Foswikitask:Item13164: added support for gzip compression of http response<br />\
Foswikitask:Item13125: CGI changes for multi_param calls<br />\
Foswikitask:Item13065: Log jsonrpc events to Foswiki event.log |
| 28 Aug 2014: | don't use DEBUG constant to toggle local debug messages as it conflicts with Assert.pm |
| 11 Dec 2013: | removed dependency on JSON::XS |
| 30 May 2013: | added support for serialising objects, and rewrote some of the documentation (Foswiki:Main/CrawfordCurrie) |
| 20 Mar 2013: | added feature to define handlers in !LocalSite.cfg (Config.spec) so that pure contribs can implement backends now |
| 1 Oct 2012: | added the async flag to the =$.jsonRpc= frontend to =$.ajax= |
| 2 Aug 2012: | fixed json2 not loaded in IE7 (Foswiki:Main/JanKrueger) |
| 16 Apr 2012: | fixed =jsonrpc= for apache's suexec |
| 10 Jan 2012: | fixed perl dependencies; \
added =redirectto= url parameter similar to the standard foswiki rest handler |
| 10 May 2011: | fixed jsonrpc script to work on old foswikis; \
fixed multi-value params; \
fixed compatibility with various JSON cpan libraries |
| 29 Apr 2011: | initial release |
| Dependencies: | %$DEPENDENCIES% |
%META:FORM{name="PackageForm"}%
%META:FIELD{name="Author" title="Author" value="Michael Daum"}%
%META:FIELD{name="Version" title="Version" value="%25$VERSION%25"}%
%META:FIELD{name="Release" title="Release" value="%25$RELEASE%25"}%
%META:FIELD{name="Repository" title="Repository" value="https://github.com/foswiki/distro"}%
%META:FIELD{name="Copyright" title="Copyright" value="© 2011-2016 Michael Daum http://michaeldaumconsulting.com and Foswiki Contributors"}%
%META:FIELD{name="License" title="License" value="[[http://www.gnu.org/licenses/gpl.html][GPL (Gnu General Public License)]]"}%
%META:FIELD{name="Home" title="Home" value="http://foswiki.org/Extensions/JsonRpcContrib"}%
%META:FIELD{name="Support" title="Support" value="Foswiki:Support/JsonRpcContrib"}%
%META:FILEATTACHMENT{name="json2.js.gz" attr="h" comment="" date="1454519814" size="1343" user="ProjectContributor" version="1"}%
%META:FILEATTACHMENT{name="jquery.jsonrpc.js" attr="h" comment="" date="1454519814" size="1106" user="ProjectContributor" version="1"}%
%META:FILEATTACHMENT{name="jquery.jsonrpc.js.gz" attr="h" comment="" date="1454519814" size="460" user="ProjectContributor" version="1"}%
%META:FILEATTACHMENT{name="Makefile" attr="h" comment="" date="1454519814" size="136" user="ProjectContributor" version="1"}%
%META:FILEATTACHMENT{name="json2.js" attr="h" comment="" date="1454519814" size="3388" user="ProjectContributor" version="1"}%
%META:FILEATTACHMENT{name="json2.uncompressed.js" attr="h" comment="" date="1454519814" size="17409" user="ProjectContributor" version="1"}%
%META:FILEATTACHMENT{name="jquery.jsonrpc.uncompressed.js" attr="h" comment="" date="1454519814" size="1720" user="ProjectContributor" version="1"}%