diff options
author | Max Kanat-Alexander <mkanat@bugzilla.org> | 2010-04-27 21:14:36 +0200 |
---|---|---|
committer | Max Kanat-Alexander <mkanat@bugzilla.org> | 2010-04-27 21:14:36 +0200 |
commit | 62efd548bbd87e4018cee195e6c74cd8a4e13d7b (patch) | |
tree | dcb099c6e0ee35e0b9400a28ca95fa6d863d5d2f /Bugzilla/WebService/Server | |
parent | 68af4d3c22ce1cb25793af5fb9f422bbb6ebe80e (diff) | |
download | bugzilla-62efd548bbd87e4018cee195e6c74cd8a4e13d7b.tar.gz bugzilla-62efd548bbd87e4018cee195e6c74cd8a4e13d7b.tar.xz |
Bug 550727: Add JSONP Support to the JSON-RPC WebService Interface
r=dkl, a=mkanat
Diffstat (limited to 'Bugzilla/WebService/Server')
-rw-r--r-- | Bugzilla/WebService/Server/JSONRPC.pm | 69 |
1 files changed, 65 insertions, 4 deletions
diff --git a/Bugzilla/WebService/Server/JSONRPC.pm b/Bugzilla/WebService/Server/JSONRPC.pm index ae479ff5e..5ab5e4a7b 100644 --- a/Bugzilla/WebService/Server/JSONRPC.pm +++ b/Bugzilla/WebService/Server/JSONRPC.pm @@ -28,7 +28,7 @@ use Bugzilla::Error; use Bugzilla::WebService::Constants; use Bugzilla::WebService::Util qw(taint_data); -use Bugzilla::Util qw(correct_urlbase); +use Bugzilla::Util qw(correct_urlbase trim); ##################################### # Public JSON::RPC Method Overrides # @@ -58,11 +58,19 @@ sub create_json_coder { # Override the JSON::RPC method to return our CGI object instead of theirs. sub cgi { return Bugzilla->cgi; } -# Override the JSON::RPC method to use $cgi->header properly instead of -# just printing text directly. This fixes various problems, including -# sending Bugzilla's cookies properly. sub response { my ($self, $response) = @_; + + # Implement JSONP. + if (my $callback = $self->_bz_callback) { + my $content = $response->content; + $response->content("$callback($content)"); + + } + + # Use $cgi->header properly instead of just printing text directly. + # This fixes various problems, including sending Bugzilla's cookies + # properly. my $headers = $response->headers; my @header_args; foreach my $name ($headers->header_field_names) { @@ -118,6 +126,10 @@ sub retrieve_json_from_get { # before _handle. $self->{_bz_request_id} = $input{id} = $id; + # _bz_callback can throw an error, so we have to set it here, after we're + # ready to throw errors. + $self->_bz_callback(scalar $cgi->param('callback')); + if (!$cgi->param('method')) { ThrowUserError('json_rpc_get_method_required'); } @@ -345,11 +357,30 @@ sub _argument_type_check { return $params; } +########################## +# Private Custom Methods # +########################## + # _bz_method_name is stored by _find_procedure for later use. sub _bz_method_name { return $_[0]->{_bz_method_name}; } +sub _bz_callback { + my ($self, $value) = @_; + if (defined $value) { + $value = trim($value); + # We don't use \w because we don't want to allow Unicode here. + if ($value !~ /^[A-Za-z0-1_\.\[\]]+$/) { + ThrowUserError('json_rpc_invalid_callback', { callback => $value }); + } + $self->{_bz_callback} = $value; + # JSONP needs to be parsed by a JS parser, not by a JSON parser. + $self->content_type('text/javascript'); + } + return $self->{_bz_callback}; +} + 1; __END__ @@ -419,6 +450,36 @@ what version of the JSON-RPC protocol you're using, and C<id> as a URL parameter if you want there to be a specific C<id> value in the returned JSON-RPC response. +=head2 JSONP + +When calling the JSON-RPC WebService over GET, you can use the "JSONP" +method of doing cross-domain requests, if you want to access the WebService +directly on a web page from another site. JSONP is described at +L<http://bob.pythonmac.org/archives/2005/12/05/remote-json-jsonp/>. + +To use JSONP with Bugzilla's JSON-RPC WebService, simply specify a +C<callback> parameter to jsonrpc.cgi when using it via GET as described above. +For example, here's some HTML you could use to get the data from +C<Bugzilla.time> on a remote website, using JSONP: + + <script type="text/javascript" + src="http://bugzilla.example.com/jsonrpc.cgi?method=Bugzilla.time&callback=foo"> + +That would call the C<Bugzilla.time> method and pass its value to a function +called C<foo> as the only argument. All the other URL parameters (such as +C<params>, for passing in arguments to methods) that can be passed to +C<jsonrpc.cgi> during GET requests are also available, of course. The above +is just the simplest possible example. + +The values returned when using JSONP are identical to the values returned +when not using JSONP, so you will also get error messages if there is an +error. + +The C<callback> URL parameter may only contain letters, numbers, periods, and +the underscore (C<_>) character. Including any other characters will cause +Bugzilla to throw an error. (This error will be a normal JSON-RPC response, +not JSONP.) + =head1 PARAMETERS For JSON-RPC 1.0, the very first parameter should be an object containing |