Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
bugzilla
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
etersoft
bugzilla
Commits
384d1d25
Commit
384d1d25
authored
Jul 12, 2013
by
Dave Lawrence
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Bug 866927 - Enhance Bugzilla WebServices to allow data access using REST
r=glob,a=justdave
parent
8a2ac056
Show whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
1617 additions
and
7 deletions
+1617
-7
.htaccess
.htaccess
+6
-0
Bugzilla.pm
Bugzilla.pm
+3
-0
CGI.pm
Bugzilla/CGI.pm
+1
-1
Constants.pm
Bugzilla/Constants.pm
+4
-0
Error.pm
Bugzilla/Error.pm
+9
-1
Requirements.pm
Bugzilla/Install/Requirements.pm
+3
-2
Mailer.pm
Bugzilla/Mailer.pm
+2
-0
WebService.pm
Bugzilla/WebService.pm
+17
-2
Bug.pm
Bugzilla/WebService/Bug.pm
+145
-0
Bugzilla.pm
Bugzilla/WebService/Bugzilla.pm
+58
-0
Classification.pm
Bugzilla/WebService/Classification.pm
+14
-0
Constants.pm
Bugzilla/WebService/Constants.pm
+59
-0
Group.pm
Bugzilla/WebService/Group.pm
+35
-0
Product.pm
Bugzilla/WebService/Product.pm
+79
-0
REST.pm
Bugzilla/WebService/Server/REST.pm
+617
-0
Bug.pm
Bugzilla/WebService/Server/REST/Resources/Bug.pm
+152
-0
Bugzilla.pm
Bugzilla/WebService/Server/REST/Resources/Bugzilla.pm
+69
-0
Classification.pm
Bugzilla/WebService/Server/REST/Resources/Classification.pm
+49
-0
Group.pm
Bugzilla/WebService/Server/REST/Resources/Group.pm
+56
-0
Product.pm
Bugzilla/WebService/Server/REST/Resources/Product.pm
+75
-0
User.pm
Bugzilla/WebService/Server/REST/Resources/User.pm
+65
-0
User.pm
Bugzilla/WebService/User.pm
+44
-1
rest.cgi
rest.cgi
+29
-0
user-error.html.tmpl
template/en/default/global/user-error.html.tmpl
+7
-0
rest.html.tmpl
template/en/default/rest.html.tmpl
+19
-0
No files found.
.htaccess
View file @
384d1d25
...
...
@@ -26,3 +26,9 @@ Options -Indexes
</
IfModule
>
</
IfModule
>
</
IfModule
>
<
IfModule
mod_rewrite.c
>
RewriteEngine
On
RewriteBase
/866927/
RewriteRule
^rest/(.*)$ rest.cgi/$1 [NE]
</
IfModule
>
Bugzilla.pm
View file @
384d1d25
...
...
@@ -469,6 +469,9 @@ sub usage_mode {
elsif
(
$newval
==
USAGE_MODE_TEST
)
{
$class
->
error_mode
(
ERROR_MODE_TEST
);
}
elsif
(
$newval
==
USAGE_MODE_REST
)
{
$class
->
error_mode
(
ERROR_MODE_REST
);
}
else
{
ThrowCodeError
(
'usage_mode_invalid'
,
{
'invalid_usage_mode'
,
$newval
});
...
...
Bugzilla/CGI.pm
View file @
384d1d25
...
...
@@ -56,7 +56,7 @@ sub new {
# the rendering of pages.
my
$script
=
basename
(
$0
);
if
(
my
$path_info
=
$self
->
path_info
)
{
my
@whitelist
;
my
@whitelist
=
(
"rest.cgi"
)
;
Bugzilla::Hook::
process
(
'path_info_whitelist'
,
{
whitelist
=>
\
@whitelist
});
if
(
!
grep
(
$_
eq
$script
,
@whitelist
))
{
# IIS includes the full path to the script in PATH_INFO,
...
...
Bugzilla/Constants.pm
View file @
384d1d25
...
...
@@ -122,12 +122,14 @@ use Memoize;
USAGE_MODE_EMAIL
USAGE_MODE_JSON
USAGE_MODE_TEST
USAGE_MODE_REST
ERROR_MODE_WEBPAGE
ERROR_MODE_DIE
ERROR_MODE_DIE_SOAP_FAULT
ERROR_MODE_JSON_RPC
ERROR_MODE_TEST
ERROR_MODE_REST
COLOR_ERROR
COLOR_SUCCESS
...
...
@@ -459,6 +461,7 @@ use constant USAGE_MODE_XMLRPC => 2;
use
constant
USAGE_MODE_EMAIL
=>
3
;
use
constant
USAGE_MODE_JSON
=>
4
;
use
constant
USAGE_MODE_TEST
=>
5
;
use
constant
USAGE_MODE_REST
=>
6
;
# Error modes. Default set by Bugzilla->usage_mode (so ERROR_MODE_WEBPAGE
# usually). Use with Bugzilla->error_mode.
...
...
@@ -467,6 +470,7 @@ use constant ERROR_MODE_DIE => 1;
use
constant
ERROR_MODE_DIE_SOAP_FAULT
=>
2
;
use
constant
ERROR_MODE_JSON_RPC
=>
3
;
use
constant
ERROR_MODE_TEST
=>
4
;
use
constant
ERROR_MODE_REST
=>
5
;
# The ANSI colors of messages that command-line scripts use
use
constant
COLOR_ERROR
=>
'red'
;
...
...
Bugzilla/Error.pm
View file @
384d1d25
...
...
@@ -104,7 +104,8 @@ sub _throw_error {
die
(
"$message\n"
);
}
elsif
(
Bugzilla
->
error_mode
==
ERROR_MODE_DIE_SOAP_FAULT
||
Bugzilla
->
error_mode
==
ERROR_MODE_JSON_RPC
)
||
Bugzilla
->
error_mode
==
ERROR_MODE_JSON_RPC
||
Bugzilla
->
error_mode
==
ERROR_MODE_REST
)
{
# Clone the hash so we aren't modifying the constant.
my
%
error_map
=
%
{
WS_ERROR_CODE
()
};
...
...
@@ -121,10 +122,17 @@ sub _throw_error {
}
else
{
my
$server
=
Bugzilla
->
_json_server
;
my
$status_code
=
0
;
if
(
Bugzilla
->
error_mode
==
ERROR_MODE_REST
)
{
my
%
status_code_map
=
%
{
REST_STATUS_CODE_MAP
()
};
$status_code
=
$status_code_map
{
$code
}
||
$status_code_map
{
'_default'
};
}
# Technically JSON-RPC isn't allowed to have error numbers
# higher than 999, but we do this to avoid conflicts with
# the internal JSON::RPC error codes.
$server
->
raise_error
(
code
=>
100000
+
$code
,
status_code
=>
$status_code
,
message
=>
$message
,
id
=>
$server
->
{
_bz_request_id
},
version
=>
$server
->
version
);
...
...
Bugzilla/Install/Requirements.pm
View file @
384d1d25
...
...
@@ -284,7 +284,7 @@ sub OPTIONAL_MODULES {
package
=>
'JSON-RPC'
,
module
=>
'JSON::RPC'
,
version
=>
0
,
feature
=>
[
'jsonrpc'
],
feature
=>
[
'jsonrpc'
,
'rest'
],
},
{
package
=>
'JSON-XS'
,
...
...
@@ -298,7 +298,7 @@ sub OPTIONAL_MODULES {
module
=>
'Test::Taint'
,
# 1.06 no longer throws warnings with Perl 5.10+.
version
=>
1.06
,
feature
=>
[
'jsonrpc'
,
'xmlrpc'
],
feature
=>
[
'jsonrpc'
,
'xmlrpc'
,
'rest'
],
},
{
# We need the 'utf8_mode' method of HTML::Parser, for HTML::Scrubber.
...
...
@@ -397,6 +397,7 @@ use constant FEATURE_FILES => (
jsonrpc
=>
[
'Bugzilla/WebService/Server/JSONRPC.pm'
,
'jsonrpc.cgi'
],
xmlrpc
=>
[
'Bugzilla/WebService/Server/XMLRPC.pm'
,
'xmlrpc.cgi'
,
'Bugzilla/WebService.pm'
,
'Bugzilla/WebService/*.pm'
],
rest
=>
[
'Bugzilla/WebService/Server/REST.pm'
,
'rest.cgi'
],
moving
=>
[
'importxml.pl'
],
auth_ldap
=>
[
'Bugzilla/Auth/Verify/LDAP.pm'
],
auth_radius
=>
[
'Bugzilla/Auth/Verify/RADIUS.pm'
],
...
...
Bugzilla/Mailer.pm
View file @
384d1d25
...
...
@@ -136,6 +136,8 @@ sub MessageToMTA {
Bugzilla::Hook::
process
(
'mailer_before_send'
,
{
email
=>
$email
,
mailer_args
=>
\
@args
});
return
if
$email
->
header
(
'to'
)
eq
''
;
$email
->
walk_parts
(
sub
{
my
(
$part
)
=
@_
;
return
if
$part
->
parts
>
1
;
# Top-level
...
...
Bugzilla/WebService.pm
View file @
384d1d25
...
...
@@ -45,8 +45,9 @@ This is the standard API for external programs that want to interact
with Bugzilla. It provides various methods in various modules.
You can interact with this API via
L<XML-RPC|Bugzilla::WebService::Server::XMLRPC> or
L<JSON-RPC|Bugzilla::WebService::Server::JSONRPC>.
L<XML-RPC|Bugzilla::WebService::Server::XMLRPC>,
L<JSON-RPC|Bugzilla::WebService::Server::JSONRPC> or
L<REST|Bugzilla::WebService::Server::REST>.
=head1 CALLING METHODS
...
...
@@ -54,6 +55,10 @@ Methods are grouped into "packages", like C<Bug> for
L<Bugzilla::WebService::Bug>. So, for example,
L<Bugzilla::WebService::Bug/get>, is called as C<Bug.get>.
For REST, the "package" is more determined by the path
used to access the resource. See each relevant method
for specific details on how to access via REST.
=head1 PARAMETERS
The Bugzilla API takes the following various types of parameters:
...
...
@@ -172,6 +177,10 @@ Note that Bugzilla will return HTTP cookies along with the method
response when you use these arguments (just like the C<User.login> method
above).
For REST, you may also use the C<username> and C<password> variable
names instead of C<Bugzilla_login> and C<Bugzilla_password> as a
convenience.
=back
=head1 STABLE, EXPERIMENTAL, and UNSTABLE
...
...
@@ -266,6 +275,9 @@ would return something like:
{ users => [{ id => 1, name => 'user@domain.com' }] }
Note for REST, C<include_fields> may instead be a comma delimited string
for GET type requests.
=item C<exclude_fields>
C<array> An array of strings, representing the (case-sensitive) names of
...
...
@@ -295,6 +307,9 @@ would return something like:
{ users => [{ id => 1, real_name => 'John Smith' }] }
Note for REST, C<exclude_fields> may instead be a comma delimited string
for GET type requests.
=back
=head1 SEE ALSO
...
...
Bugzilla/WebService/Bug.pm
View file @
384d1d25
...
...
@@ -1075,6 +1075,10 @@ or get information about bugs that have already been filed.
See L<Bugzilla::WebService> for a description of how parameters are passed,
and what B<STABLE>, B<UNSTABLE>, and B<EXPERIMENTAL> mean.
Although the data input and output is the same for JSONRPC, XMLRPC and REST,
the directions for how to access the data via REST is noted in each method
where applicable.
=head1 Utility Functions
=head2 fields
...
...
@@ -1088,6 +1092,21 @@ B<UNSTABLE>
Get information about valid bug fields, including the lists of legal values
for each field.
=item B<REST>
You have several options for retreiving information about fields. The first
part is the request method and the rest is the related path needed.
To get information about all fields:
GET /field/bug
To get information related to a single field:
GET /field/bug/<id_or_name>
The returned data format is the same as below.
=item B<Params>
You can pass either field ids or field names.
...
...
@@ -1288,6 +1307,8 @@ You specified an invalid field name or id.
=item C<is_active> return key for C<values> was added in Bugzilla B<4.4>.
=item REST API call added in Bugzilla B<5.0>
=back
=back
...
...
@@ -1303,6 +1324,18 @@ B<DEPRECATED> - Use L</fields> instead.
Tells you what values are allowed for a particular field.
=item B<REST>
To get information on the values for a field based on field name:
GET /field/bug/<field_name>/values
To get information based on field name and a specific product:
GET /field/bug/<field_name>/<product_id>/values
The returned data format is the same as below.
=item B<Params>
=over
...
...
@@ -1335,6 +1368,14 @@ You specified a field that doesn't exist or isn't a drop-down field.
=back
=item B<History>
=over
=item REST API call added in Bugzilla B<5.0>.
=back
=back
=head1 Bug Information
...
...
@@ -1353,6 +1394,18 @@ and/or attachment ids.
B<Note>: Private attachments will only be returned if you are in the
insidergroup or if you are the submitter of the attachment.
=item B<REST>
To get all current attachments for a bug:
GET /bug/<bug_id>/attachment
To get a specific attachment based on attachment ID:
GET /bug/attachment/<attachment_id>
The returned data format is the same as below.
=item B<Params>
B<Note>: At least one of C<ids> or C<attachment_ids> is required.
...
...
@@ -1550,6 +1603,8 @@ C<summary>.
=item The C<flags> array was added in Bugzilla B<4.4>.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
...
...
@@ -1566,6 +1621,18 @@ B<STABLE>
This allows you to get data about comments, given a list of bugs
and/or comment ids.
=item B<REST>
To get all comments for a particular bug using the bug ID or alias:
GET /bug/<id_or_alias>/comment
To get a specific comment based on the comment ID:
GET /bug/comment/<comment_id>
The returned data format is the same as below.
=item B<Params>
B<Note>: At least one of C<ids> or C<comment_ids> is required.
...
...
@@ -1711,6 +1778,8 @@ C<creator>.
=item C<creation_time> was added in Bugzilla B<4.4>.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
...
...
@@ -1728,6 +1797,14 @@ Gets information about particular bugs in the database.
Note: Can also be called as "get_bugs" for compatibilty with Bugzilla 3.0 API.
=item B<REST>
To get information about a particular bug using its ID or alias:
GET /bug/<id_or_alias>
The returned data format is the same as below.
=item B<Params>
In addition to the parameters below, this method also accepts the
...
...
@@ -2060,6 +2137,8 @@ You do not have access to the bug_id you specified.
=item The following properties were added to this method's return values
in Bugzilla B<3.4>:
=item REST API call added in Bugzilla B<5.0>
=over
=item For C<bugs>
...
...
@@ -2117,6 +2196,14 @@ B<EXPERIMENTAL>
Gets the history of changes for particular bugs in the database.
=item B<REST>
To get the history for a specific bug ID:
GET /bug/<bug_id>/history
The returned data format will be the same as below.
=item B<Params>
=over
...
...
@@ -2208,6 +2295,8 @@ The same as L</get>.
consistent with other methods. Since Bugzilla B<4.4>, they now match
names used by L<Bug.update|/"update"> for consistency.
=item REST API call added Bugzilla B<5.0>.
=back
=back
...
...
@@ -2223,6 +2312,14 @@ B<UNSTABLE>
Allows you to search for bugs based on particular criteria.
=item <REST>
To search for bugs:
GET /bug
The URL parameters and the returned data format are the same as below.
=item B<Params>
Unless otherwise specified in the description of a parameter, bugs are
...
...
@@ -2408,6 +2505,8 @@ in Bugzilla B<4.0>.
C<limit> is set equal to zero. Otherwise maximum results returned are limited
by system configuration.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
...
...
@@ -2434,6 +2533,15 @@ The WebService interface may allow you to set things other than those listed
here, but realize that anything undocumented is B<UNSTABLE> and will very
likely change in the future.
=item B<REST>
To create a new bug in Bugzilla:
POST /bug
The params to include in the POST body as well as the returned data format,
are the same as below.
=item B<Params>
Some params must be set, or an error will be thrown. These params are
...
...
@@ -2598,6 +2706,8 @@ loop errors had a generic code of C<32000>.
=item The ability to file new bugs with a C<resolution> was added in
Bugzilla B<4.4>.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
...
...
@@ -2613,6 +2723,16 @@ B<STABLE>
This allows you to add an attachment to a bug in Bugzilla.
=item B<REST>
To create attachment on a current bug:
POST /bug/<bug_id>/attachment
The params to include in the POST body, as well as the returned
data format are the same as below. The C<ids> param will be
overridden as it it pulled from the URL path.
=item B<Params>
=over
...
...
@@ -2710,6 +2830,8 @@ You set the "data" field to an empty string.
=item The return value has changed in Bugzilla B<4.4>.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
...
...
@@ -2725,6 +2847,15 @@ B<STABLE>
This allows you to add a comment to a bug in Bugzilla.
=item B<REST>
To create a comment on a current bug:
POST /bug/<bug_id>/comment
The params to include in the POST body as well as the returned data format,
are the same as below.
=item B<Params>
=over
...
...
@@ -2800,6 +2931,8 @@ purposes if you wish.
=item Before Bugzilla B<3.6>, error 54 and error 114 had a generic error
code of 32000.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
...
...
@@ -2816,6 +2949,16 @@ B<UNSTABLE>
Allows you to update the fields of a bug. Automatically sends emails
out about the changes.
=item B<REST>
To update the fields of a current bug:
PUT /bug/<bug_id>
The params to include in the PUT body as well as the returned data format,
are the same as below. The C<ids> param will be overridden as it is
pulled from the URL path.
=item B<Params>
=over
...
...
@@ -3260,6 +3403,8 @@ rules don't allow that change.
=item Added in Bugzilla B<4.0>.
=item REST API call added Bugzilla B<5.0>.
=back
=back
...
...
Bugzilla/WebService/Bugzilla.pm
View file @
384d1d25
...
...
@@ -181,6 +181,10 @@ This provides functions that tell you about Bugzilla in general.
See L<Bugzilla::WebService> for a description of how parameters are passed,
and what B<STABLE>, B<UNSTABLE>, and B<EXPERIMENTAL> mean.
Although the data input and output is the same for JSONRPC, XMLRPC and REST,
the directions for how to access the data via REST is noted in each method
where applicable.
=head2 version
B<STABLE>
...
...
@@ -191,6 +195,12 @@ B<STABLE>
Returns the current version of Bugzilla.
=item B<REST>
GET /version
The returned data format is the same as below.
=item B<Params> (none)
=item B<Returns>
...
...
@@ -200,6 +210,14 @@ string.
=item B<Errors> (none)
=item B<History>
=over
=item REST API call added in Bugzilla B<5.0>.
=back
=back
=head2 extensions
...
...
@@ -213,6 +231,12 @@ B<EXPERIMENTAL>
Gets information about the extensions that are currently installed and enabled
in this Bugzilla.
=item B<REST>
GET /extensions
The returned data format is the same as below.
=item B<Params> (none)
=item B<Returns>
...
...
@@ -243,6 +267,8 @@ The return value looks something like this:
that the extensions define themselves. Before 3.6, the names of the
extensions depended on the directory they were in on the Bugzilla server.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
...
...
@@ -258,6 +284,12 @@ Use L</time> instead.
Returns the timezone that Bugzilla expects dates and times in.
=item B<REST>
GET /timezone
The returned data format is the same as below.
=item B<Params> (none)
=item B<Returns>
...
...
@@ -272,6 +304,8 @@ string in (+/-)XXXX (RFC 2822) format.
=item As of Bugzilla B<3.6>, the timezone returned is always C<+0000>
(the UTC timezone).
=item REST API call added in Bugzilla B<5.0>.
=back
=back
...
...
@@ -288,6 +322,12 @@ B<STABLE>
Gets information about what time the Bugzilla server thinks it is, and
what timezone it's running in.
=item B<REST>
GET /time
The returned data format is the same as below.
=item B<Params> (none)
=item B<Returns>
...
...
@@ -348,6 +388,8 @@ with versions of Bugzilla before 3.6.)
were in the UTC timezone, instead of returning information in the server's
local timezone.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
...
...
@@ -362,6 +404,12 @@ B<UNSTABLE>
Returns parameter values currently used in this Bugzilla.
=item B<REST>
GET /parameters
The returned data format is the same as below.
=item B<Params> (none)
=item B<Returns>
...
...
@@ -419,6 +467,8 @@ never be stable.
=item Added in Bugzilla B<4.4>.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
...
...
@@ -433,6 +483,12 @@ B<EXPERIMENTAL>
Gets the latest time of the audit_log table.
=item B<REST>
GET /last_audit_time
The returned data format is the same as below.
=item B<Params>
You can pass the optional parameter C<class> to get the maximum for only
...
...
@@ -460,6 +516,8 @@ at_time from the audit_log.
=item Added in Bugzilla B<4.4>.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
Bugzilla/WebService/Classification.pm
View file @
384d1d25
...
...
@@ -94,6 +94,10 @@ You will be able to get information about them as well as manipulate them.
See L<Bugzilla::WebService> for a description of how parameters are passed,
and what B<STABLE>, B<UNSTABLE>, and B<EXPERIMENTAL> mean.
Although the data input and output is the same for JSONRPC, XMLRPC and REST,
the directions for how to access the data via REST is noted in each method
where applicable.
=head1 Classification Retrieval
=head2 get
...
...
@@ -106,6 +110,14 @@ B<EXPERIMENTAL>
Returns a hash containing information about a set of classifications.
=item B<REST>
To return information on a single classification:
GET /classification/<classification_id_or_name>
The returned data format will be the same as below.
=item B<Params>
In addition to the parameters below, this method also accepts the
...
...
@@ -190,6 +202,8 @@ Classification is not enabled on this installation.
=item Added in Bugzilla B<4.4>.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
...
...
Bugzilla/WebService/Constants.pm
View file @
384d1d25
...
...
@@ -14,9 +14,22 @@ use parent qw(Exporter);
our
@EXPORT
=
qw(
WS_ERROR_CODE
STATUS_OK
STATUS_CREATED
STATUS_ACCEPTED
STATUS_NO_CONTENT
STATUS_MULTIPLE_CHOICES
STATUS_BAD_REQUEST
STATUS_NOT_FOUND
STATUS_GONE
REST_STATUS_CODE_MAP
ERROR_UNKNOWN_FATAL
ERROR_UNKNOWN_TRANSIENT
XMLRPC_CONTENT_TYPE_WHITELIST
REST_CONTENT_TYPE_WHITELIST
WS_DISPATCH
)
;
...
...
@@ -174,6 +187,45 @@ use constant WS_ERROR_CODE => {
json_rpc_invalid_callback
=>
32611
,
xmlrpc_illegal_content_type
=>
32612
,
json_rpc_illegal_content_type
=>
32613
,
rest_invalid_resource
=>
32614
,
};
# RESTful webservices use the http status code
# to describe whether a call was successful or
# to describe the type of error that occurred.
use
constant
STATUS_OK
=>
200
;
use
constant
STATUS_CREATED
=>
201
;
use
constant
STATUS_ACCEPTED
=>
202
;
use
constant
STATUS_NO_CONTENT
=>
204
;
use
constant
STATUS_MULTIPLE_CHOICES
=>
300
;
use
constant
STATUS_BAD_REQUEST
=>
400
;
use
constant
STATUS_NOT_AUTHORIZED
=>
401
;
use
constant
STATUS_NOT_FOUND
=>
404
;
use
constant
STATUS_GONE
=>
410
;
# The integer value is the error code above returned by
# the related webvservice call. We choose the appropriate
# http status code based on the error code or use the
# default STATUS_BAD_REQUEST.
use
constant
REST_STATUS_CODE_MAP
=>
{
51
=>
STATUS_NOT_FOUND
,
101
=>
STATUS_NOT_FOUND
,
102
=>
STATUS_NOT_AUTHORIZED
,
106
=>
STATUS_NOT_AUTHORIZED
,
109
=>
STATUS_NOT_AUTHORIZED
,
110
=>
STATUS_NOT_AUTHORIZED
,
113
=>
STATUS_NOT_AUTHORIZED
,
115
=>
STATUS_NOT_AUTHORIZED
,
120
=>
STATUS_NOT_AUTHORIZED
,
300
=>
STATUS_NOT_AUTHORIZED
,
301
=>
STATUS_NOT_AUTHORIZED
,
302
=>
STATUS_NOT_AUTHORIZED
,
303
=>
STATUS_NOT_AUTHORIZED
,
304
=>
STATUS_NOT_AUTHORIZED
,
410
=>
STATUS_NOT_AUTHORIZED
,
504
=>
STATUS_NOT_AUTHORIZED
,
505
=>
STATUS_NOT_AUTHORIZED
,
_default
=>
STATUS_BAD_REQUEST
};
# These are the fallback defaults for errors not in ERROR_CODE.
...
...
@@ -187,6 +239,13 @@ use constant XMLRPC_CONTENT_TYPE_WHITELIST => qw(
application/xml
)
;
use
constant
REST_CONTENT_TYPE_WHITELIST
=>
qw(
text/html
application/javascript
application/json
text/javascript
)
;
sub
WS_DISPATCH
{
# We "require" here instead of "use" above to avoid a dependency loop.
require
Bugzilla::
Hook
;
...
...
Bugzilla/WebService/Group.pm
View file @
384d1d25
...
...
@@ -113,6 +113,10 @@ get information about them.
See L<Bugzilla::WebService> for a description of how parameters are passed,
and what B<STABLE>, B<UNSTABLE>, and B<EXPERIMENTAL> mean.
Although the data input and output is the same for JSONRPC, XMLRPC and REST,
the directions for how to access the data via REST is noted in each method
where applicable.
=head1 Group Creation and Modification
=head2 create
...
...
@@ -125,6 +129,13 @@ B<UNSTABLE>
This allows you to create a new group in Bugzilla.
=item B<REST>
POST /group
The params to include in the POST body as well as the returned data format,
are the same as below.
=item B<Params>
Some params must be set, or an error will be thrown. These params are
...
...
@@ -188,6 +199,14 @@ You specified an invalid regular expression in the C<user_regexp> field.
=back
=item B<History>
=over
=item REST API call added in Bugzilla B<5.0>.
=back
=back
=head2 update
...
...
@@ -200,6 +219,14 @@ B<UNSTABLE>
This allows you to update a group in Bugzilla.
=item B<REST>
PUT /group/<group_name_or_id>
The params to include in the PUT body as well as the returned data format,
are the same as below. The C<ids> param will be overridden as it is pulled
from the URL path.
=item B<Params>
At least C<ids> or C<names> must be set, or an error will be thrown.
...
...
@@ -278,6 +305,14 @@ comma-and-space-separated list if multiple values were removed.
The same as L</create>.
=item B<History>
=over
=item REST API call added in Bugzilla B<5.0>.
=back
=back
=cut
Bugzilla/WebService/Product.pm
View file @
384d1d25
...
...
@@ -336,6 +336,10 @@ get information about them.
See L<Bugzilla::WebService> for a description of how parameters are passed,
and what B<STABLE>, B<UNSTABLE>, and B<EXPERIMENTAL> mean.
Although the data input and output is the same for JSONRPC, XMLRPC and REST,
the directions for how to access the data via REST is noted in each method
where applicable.
=head1 List Products
=head2 get_selectable_products
...
...
@@ -348,6 +352,12 @@ B<EXPERIMENTAL>
Returns a list of the ids of the products the user can search on.
=item B<REST>
GET /product?type=selectable
the returned data format is same as below.
=item B<Params> (none)
=item B<Returns>
...
...
@@ -357,6 +367,14 @@ ids.
=item B<Errors> (none)
=item B<History>
=over
=item REST API call added in Bugzilla B<5.0>.
=back
=back
=head2 get_enterable_products
...
...
@@ -370,6 +388,12 @@ B<EXPERIMENTAL>
Returns a list of the ids of the products the user can enter bugs
against.
=item B<REST>
GET /product?type=enterable
the returned data format is same as below.
=item B<Params> (none)
=item B<Returns>
...
...
@@ -379,6 +403,14 @@ ids.
=item B<Errors> (none)
=item B<History>
=over
=item REST API call added in Bugzilla B<5.0>.
=back
=back
=head2 get_accessible_products
...
...
@@ -392,6 +424,12 @@ B<UNSTABLE>
Returns a list of the ids of the products the user can search or enter
bugs against.
=item B<REST>
GET /product?type=accessible
the returned data format is same as below.
=item B<Params> (none)
=item B<Returns>
...
...
@@ -401,6 +439,14 @@ ids.
=item B<Errors> (none)
=item B<History>
=over
=item REST API call added in Bugzilla B<5.0>.
=back
=back
=head2 get
...
...
@@ -417,6 +463,12 @@ B<Note>: You must at least specify one of C<ids> or C<names>.
B<Note>: Can also be called as "get_products" for compatibilty with Bugzilla 3.0 API.
=item B<REST>
GET /product/<product_id_or_name>
the returned data format is same as below.
=item B<Params>
In addition to the parameters below, this method also accepts the
...
...
@@ -612,6 +664,8 @@ been removed.
=item In Bugzilla B<4.4>, C<flag_types> was added to the fields returned
by C<get>.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
...
...
@@ -628,6 +682,13 @@ B<EXPERIMENTAL>
This allows you to create a new product in Bugzilla.
=item B<REST>
POST /product
The params to include in the POST body as well as the returned data format,
are the same as below.
=item B<Params>
Some params must be set, or an error will be thrown. These params are
...
...
@@ -709,6 +770,14 @@ You must specify a version for this product.
=back
=item B<History>
=over
=item REST API call added in Bugzilla B<5.0>.
=back
=back
=head2 update
...
...
@@ -721,6 +790,14 @@ B<EXPERIMENTAL>
This allows you to update a product in Bugzilla.
=item B<REST>
PUT /product/<product_id_or_name>
The params to include in the PUT body as well as the returned data format,
are the same as below. The C<ids> and C<names> params will be overridden as
it is pulled from the URL path.
=item B<Params>
B<Note:> The following parameters specify which products you are updating.
...
...
@@ -859,6 +936,8 @@ You must define a default milestone.
=item Added in Bugzilla B<4.4>.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
...
...
Bugzilla/WebService/Server/REST.pm
0 → 100644
View file @
384d1d25
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
package
Bugzilla::WebService::Server::
REST
;
use
5.10.1
;
use
strict
;
use
parent
qw(Bugzilla::WebService::Server::JSONRPC)
;
use
Bugzilla
;
use
Bugzilla::
Constants
;
use
Bugzilla::
Error
;
use
Bugzilla::WebService::
Constants
;
use
Bugzilla::WebService::
Util
qw(taint_data)
;
use
Bugzilla::
Util
qw(correct_urlbase html_quote)
;
# Load resource modules
use
Bugzilla::WebService::Server::REST::Resources::
Bug
;
use
Bugzilla::WebService::Server::REST::Resources::
Bugzilla
;
use
Bugzilla::WebService::Server::REST::Resources::
Classification
;
use
Bugzilla::WebService::Server::REST::Resources::
Group
;
use
Bugzilla::WebService::Server::REST::Resources::
Product
;
use
Bugzilla::WebService::Server::REST::Resources::
User
;
use
Scalar::
Util
qw(blessed reftype)
;
use
MIME::
Base64
qw(decode_base64)
;
###########################
# Public Method Overrides #
###########################
sub
handle
{
my
(
$self
)
=
@_
;
# Determine how the data should be represented. We do this early so
# errors will also be returned with the proper content type.
$self
->
content_type
(
$self
->
_best_content_type
(
REST_CONTENT_TYPE_WHITELIST
()));
# Using current path information, decide which class/method to
# use to serve the request. Throw error if no resource was found
# unless we were looking for OPTIONS
if
(
!
$self
->
_find_resource
(
$self
->
cgi
->
path_info
))
{
if
(
$self
->
request
->
method
eq
'OPTIONS'
&&
$self
->
bz_rest_options
)
{
my
$response
=
$self
->
response_header
(
STATUS_OK
,
""
);
my
$options_string
=
join
(
', '
,
@
{
$self
->
bz_rest_options
});
$response
->
header
(
'Allow'
=>
$options_string
,
'Access-Control-Allow-Methods'
=>
$options_string
);
return
$self
->
response
(
$response
);
}
ThrowUserError
(
"rest_invalid_resource"
,
{
path
=>
$self
->
cgi
->
path_info
,
method
=>
$self
->
request
->
method
});
}
# Dispatch to the proper module
my
$class
=
$self
->
bz_class_name
;
my
(
$path
)
=
$class
=~
/::([^:]+)$/
;
$self
->
path_info
(
$path
);
delete
$self
->
{
dispatch_path
};
$self
->
dispatch
({
$path
=>
$class
});
my
$params
=
$self
->
_retrieve_json_params
;
$self
->
_fix_credentials
(
$params
);
# Fix includes/excludes for each call
rest_include_exclude
(
$params
);
# Set callback name if exists
$self
->
_bz_callback
(
$params
->
{
'callback'
})
if
$params
->
{
'callback'
};
Bugzilla
->
input_params
(
$params
);
# Set the JSON version to 1.1 and the id to the current urlbase
# also set up the correct handler method
my
$obj
=
{
version
=>
'1.1'
,
id
=>
correct_urlbase
(),
method
=>
$self
->
bz_method_name
,
params
=>
$params
};
# Execute the handler
my
$result
=
$self
->
_handle
(
$obj
);
if
(
!
$self
->
error_response_header
)
{
return
$self
->
response
(
$self
->
response_header
(
$self
->
bz_success_code
||
STATUS_OK
,
$result
));
}
$self
->
response
(
$self
->
error_response_header
);
}
sub
response
{
my
(
$self
,
$response
)
=
@_
;
# If we have thrown an error, the 'error' key will exist
# otherwise we use 'result'. JSONRPC returns other data
# along with the result/error such as version and id which
# we will strip off for REST calls.
my
$content
=
$response
->
content
;
my
$json_data
=
{};
if
(
$content
)
{
$json_data
=
$self
->
json
->
decode
(
$content
);
}
my
$result
=
{};
if
(
exists
$json_data
->
{
error
})
{
$result
=
$json_data
->
{
error
};
$result
->
{
error
}
=
$self
->
type
(
'boolean'
,
1
);
delete
$result
->
{
'name'
};
# Remove JSONRPCError
}
elsif
(
exists
$json_data
->
{
result
})
{
$result
=
$json_data
->
{
result
};
}
# Access Control
$response
->
header
(
"Access-Control-Allow-Origin"
,
"*"
);
# If accessing through web browser, then display in readable format
if
(
$self
->
content_type
eq
'text/html'
)
{
$result
=
$self
->
json
->
pretty
->
canonical
->
encode
(
$result
);
my
$template
=
Bugzilla
->
template
;
$content
=
""
;
$template
->
process
(
"rest.html.tmpl"
,
{
result
=>
$result
},
\
$content
)
||
ThrowTemplateError
(
$template
->
error
());
$response
->
content_type
(
'text/html'
);
}
else
{
$content
=
$self
->
json
->
encode
(
$result
);
}
$response
->
content
(
$content
);
$self
->
SUPER::
response
(
$response
);
}
#######################################
# Bugzilla::WebService Implementation #
#######################################
sub
handle_login
{
my
$self
=
shift
;
# If we're being called using GET, we don't allow cookie-based or Env
# login, because GET requests can be done cross-domain, and we don't
# want private data showing up on another site unless the user
# explicitly gives that site their username and password. (This is
# particularly important for JSONP, which would allow a remote site
# to use private data without the user's knowledge, unless we had this
# protection in place.)
if
(
!
grep
(
$_
eq
$self
->
request
->
method
,
(
'POST'
,
'PUT'
)))
{
# XXX There's no particularly good way for us to get a parameter
# to Bugzilla->login at this point, so we pass this information
# around using request_cache, which is a bit of a hack. The
# implementation of it is in Bugzilla::Auth::Login::Stack.
Bugzilla
->
request_cache
->
{
'auth_no_automatic_login'
}
=
1
;
}
my
$class
=
$self
->
bz_class_name
;
my
$method
=
$self
->
bz_method_name
;
my
$full_method
=
$class
.
"."
.
$method
;
# Bypass JSONRPC::handle_login
Bugzilla::WebService::
Server
->
handle_login
(
$class
,
$method
,
$full_method
);
}
############################
# Private Method Overrides #
############################
# We do not want to run Bugzilla::WebService::Server::JSONRPC->_find_prodedure
# as it determines the method name differently.
sub
_find_procedure
{
my
$self
=
shift
;
if
(
$self
->
isa
(
'JSON::RPC::Server::CGI'
))
{
return
JSON::RPC::Server::
_find_procedure
(
$self
,
@_
);
}
else
{
return
JSON::RPC::Legacy::Server::
_find_procedure
(
$self
,
@_
);
}
}
sub
_argument_type_check
{
my
$self
=
shift
;
my
$params
;
if
(
$self
->
isa
(
'JSON::RPC::Server::CGI'
))
{
$params
=
JSON::RPC::Server::
_argument_type_check
(
$self
,
@_
);
}
else
{
$params
=
JSON::RPC::Legacy::Server::
_argument_type_check
(
$self
,
@_
);
}
# JSON-RPC 1.0 requires all parameters to be passed as an array, so
# we just pull out the first item and assume it's an object.
my
$params_is_array
;
if
(
ref
$params
eq
'ARRAY'
)
{
$params
=
$params
->
[
0
];
$params_is_array
=
1
;
}
taint_data
(
$params
);
Bugzilla
->
input_params
(
$params
);
# Now, convert dateTime fields on input.
my
$method
=
$self
->
bz_method_name
;
my
$pkg
=
$self
->
{
dispatch_path
}
->
{
$self
->
path_info
};
my
@date_fields
=
@
{
$pkg
->
DATE_FIELDS
->
{
$method
}
||
[]
};
foreach
my
$field
(
@date_fields
)
{
if
(
defined
$params
->
{
$field
})
{
my
$value
=
$params
->
{
$field
};
if
(
ref
$value
eq
'ARRAY'
)
{
$params
->
{
$field
}
=
[
map
{
$self
->
datetime_format_inbound
(
$_
)
}
@$value
];
}
else
{
$params
->
{
$field
}
=
$self
->
datetime_format_inbound
(
$value
);
}
}
}
my
@base64_fields
=
@
{
$pkg
->
BASE64_FIELDS
->
{
$method
}
||
[]
};
foreach
my
$field
(
@base64_fields
)
{
if
(
defined
$params
->
{
$field
})
{
$params
->
{
$field
}
=
decode_base64
(
$params
->
{
$field
});
}
}
# This is the best time to do login checks.
$self
->
handle_login
();
# Bugzilla::WebService packages call internal methods like
# $self->_some_private_method. So we have to inherit from
# that class as well as this Server class.
my
$new_class
=
ref
(
$self
)
.
'::'
.
$pkg
;
my
$isa_string
=
'our @ISA = qw('
.
ref
(
$self
)
.
" $pkg)"
;
eval
"package $new_class;$isa_string;"
;
bless
$self
,
$new_class
;
if
(
$params_is_array
)
{
$params
=
[
$params
];
}
return
$params
;
}
###################
# Utility Methods #
###################
sub
bz_method_name
{
my
(
$self
,
$method
)
=
@_
;
$self
->
{
_bz_method_name
}
=
$method
if
$method
;
return
$self
->
{
_bz_method_name
};
}
sub
bz_class_name
{
my
(
$self
,
$class
)
=
@_
;
$self
->
{
_bz_class_name
}
=
$class
if
$class
;
return
$self
->
{
_bz_class_name
};
}
sub
bz_success_code
{
my
(
$self
,
$value
)
=
@_
;
$self
->
{
_bz_success_code
}
=
$value
if
$value
;
return
$self
->
{
_bz_success_code
};
}
sub
bz_rest_params
{
my
(
$self
,
$params
)
=
@_
;
$self
->
{
_bz_rest_params
}
=
$params
if
$params
;
return
$self
->
{
_bz_rest_params
};
}
sub
bz_rest_options
{
my
(
$self
,
$options
)
=
@_
;
$self
->
{
_bz_rest_options
}
=
$options
if
$options
;
return
$self
->
{
_bz_rest_options
};
}
sub
rest_include_exclude
{
my
(
$params
)
=
@_
;
# _all is same as default columns
if
(
$params
->
{
'include_fields'
}
&&
(
$params
->
{
'include_fields'
}
eq
'_all'
||
$params
->
{
'include_fields'
}
eq
'_default'
))
{
delete
$params
->
{
'include_fields'
};
delete
$params
->
{
'exclude_fields'
}
if
$params
->
{
'exclude_fields'
};
}
if
(
$params
->
{
'include_fields'
}
&&
!
ref
$params
->
{
'include_fields'
})
{
$params
->
{
'include_fields'
}
=
[
split
(
/[\s+,]/
,
$params
->
{
'include_fields'
})
];
}
if
(
$params
->
{
'exclude_fields'
}
&&
!
ref
$params
->
{
'exclude_fields'
})
{
$params
->
{
'exclude_fields'
}
=
[
split
(
/[\s+,]/
,
$params
->
{
'exclude_fields'
})
];
}
return
$params
;
}
##########################
# Private Custom Methods #
##########################
sub
_retrieve_json_params
{
my
$self
=
shift
;
# Make a copy of the current input_params rather than edit directly
my
$params
=
{};
%
{
$params
}
=
%
{
Bugzilla
->
input_params
};
# First add any params we were able to pull out of the path
# based on the resource regexp
%
{
$params
}
=
(
%
{
$params
},
%
{
$self
->
bz_rest_params
})
if
$self
->
bz_rest_params
;
# Merge any additional query key/values with $obj->{params} if not a GET request
# We do this manually cause CGI.pm doesn't understand JSON strings.
if
(
$self
->
request
->
method
ne
'GET'
)
{
my
$extra_params
=
{};
my
$json
=
delete
$params
->
{
'POSTDATA'
}
||
delete
$params
->
{
'PUTDATA'
};
if
(
$json
)
{
eval
{
$extra_params
=
$self
->
json
->
decode
(
$json
);
};
if
(
$@
)
{
ThrowUserError
(
'json_rpc_invalid_params'
,
{
err_msg
=>
$@
});
}
}
%
{
$params
}
=
(
%
{
$params
},
%
{
$extra_params
})
if
%
{
$extra_params
};
}
return
$params
;
}
sub
_find_resource
{
my
(
$self
,
$path
)
=
@_
;
# Load in the WebService module from the dispatch map and then call
# $module->rest_resources to get the resources array ref.
my
$resources
=
{};
foreach
my
$module
(
values
%
{
$self
->
{
dispatch_path
}
})
{
eval
(
"require $module"
)
||
die
$@
;
next
if
!
$module
->
can
(
'rest_resources'
);
$resources
->
{
$module
}
=
$module
->
rest_resources
;
}
# Use the resources hash from each module loaded earlier to determine
# which handler to use based on a regex match of the CGI path.
# Also any matches found in the regex will be passed in later to the
# handler for possible use.
my
$request_method
=
$self
->
request
->
method
;
my
(
@matches
,
$handler_found
,
$handler_method
,
$handler_class
);
foreach
my
$class
(
keys
%
{
$resources
})
{
# The resource data for each module needs to be
# an array ref with an even number of elements
# to work correctly.
next
if
(
ref
$resources
->
{
$class
}
ne
'ARRAY'
||
scalar
@
{
$resources
->
{
$class
}
}
%
2
!=
0
);
while
(
my
$regex
=
shift
@
{
$resources
->
{
$class
}
})
{
my
$options_data
=
shift
@
{
$resources
->
{
$class
}
};
next
if
ref
$options_data
ne
'HASH'
;
if
(
@matches
=
(
$path
=~
$regex
))
{
# If a specific path is accompanied by a OPTIONS request
# method, the user is asking for a list of possible request
# methods for a specific path.
$self
->
bz_rest_options
([
keys
%
{
$options_data
}
]);
if
(
$options_data
->
{
$request_method
})
{
my
$resource_data
=
$options_data
->
{
$request_method
};
$self
->
bz_class_name
(
$class
);
# The method key/value can be a simple scalar method name
# or a anonymous subroutine so we execute it here.
my
$method
=
ref
$resource_data
->
{
method
}
eq
'CODE'
?
$resource_data
->
{
method
}
->
(
$self
)
:
$resource_data
->
{
method
};
$self
->
bz_method_name
(
$method
);
# Pull out any parameters parsed from the URL path
# and store them for use by the method.
if
(
$resource_data
->
{
params
})
{
$self
->
bz_rest_params
(
$resource_data
->
{
params
}
->
(
@matches
));
}
# If a special success code is needed for this particular
# method, then store it for later when generating response.
if
(
$resource_data
->
{
success_code
})
{
$self
->
bz_success_code
(
$resource_data
->
{
success_code
});
}
$handler_found
=
1
;
}
}
last
if
$handler_found
;
}
last
if
$handler_found
;
}
return
$handler_found
;
}
sub
_fix_credentials
{
my
(
$self
,
$params
)
=
@_
;
# Allow user to pass in &username=foo&password=bar
if
(
exists
$params
->
{
'username'
}
&&
exists
$params
->
{
'password'
})
{
$params
->
{
'Bugzilla_login'
}
=
delete
$params
->
{
'username'
};
$params
->
{
'Bugzilla_password'
}
=
delete
$params
->
{
'password'
};
}
}
sub
_best_content_type
{
my
(
$self
,
@types
)
=
@_
;
return
(
$self
->
_simple_content_negotiation
(
@types
))[
0
]
||
'*/*'
;
}
sub
_simple_content_negotiation
{
my
(
$self
,
@types
)
=
@_
;
my
@accept_types
=
$self
->
_get_content_prefs
();
my
$score
=
sub
{
$self
->
_score_type
(
shift
,
@accept_types
)
};
return
sort
{
$score
->
(
$b
)
<=>
$score
->
(
$a
)}
@types
;
}
sub
_score_type
{
my
(
$self
,
$type
,
@accept_types
)
=
@_
;
my
$score
=
scalar
(
@accept_types
);
for
my
$accept_type
(
@accept_types
)
{
return
$score
if
$type
eq
$accept_type
;
$score
--
;
}
return
0
;
}
sub
_get_content_prefs
{
my
$self
=
shift
;
my
$default_weight
=
1
;
my
@prefs
;
# Parse the Accept header, and save type name, score, and position.
my
@accept_types
=
split
/,/
,
$self
->
cgi
->
http
(
'accept'
)
||
''
;
my
$order
=
0
;
for
my
$accept_type
(
@accept_types
)
{
my
(
$weight
)
=
(
$accept_type
=~
/q=(\d\.\d+|\d+)/
);
my
(
$name
)
=
(
$accept_type
=~
m
#(\S+/[^;]+)#);
next
unless
$name
;
push
@prefs
,
{
name
=>
$name
,
order
=>
$order
++
};
if
(
defined
$weight
)
{
$prefs
[
-
1
]
->
{
score
}
=
$weight
;
}
else
{
$prefs
[
-
1
]
->
{
score
}
=
$default_weight
;
$default_weight
-=
0.001
;
}
}
# Sort the types by score, subscore by order, and pull out just the name
@prefs
=
map
{
$_
->
{
name
}}
sort
{
$b
->
{
score
}
<=>
$a
->
{
score
}
||
$a
->
{
order
}
<=>
$b
->
{
order
}}
@prefs
;
return
@prefs
,
'*/*'
;
# Allows allow for */*
}
1
;
__END__
=head1 NAME
Bugzilla::WebService::Server::REST - The REST Interface to Bugzilla
=head1 DESCRIPTION
This documentation describes things about the Bugzilla WebService that
are specific to REST. For a general overview of the Bugzilla WebServices,
see L<Bugzilla::WebService>. The L<Bugzilla::WebService::Server::REST>
module is a sub-class of L<Bugzilla::WebService::Server::JSONRPC> so any
method documentation not found here can be viewed in it's POD.
Please note that I<everything> about this REST interface is
B<EXPERIMENTAL>. If you want a fully stable API, please use the
C<Bugzilla::WebService::Server::XMLRPC|XML-RPC> interface.
=head1 CONNECTING
The endpoint for the REST interface is the C<rest.cgi> script in
your Bugzilla installation. If using Apache and mod_rewrite is installed
and enabled, you can also use /rest/ as your endpoint. For example, if your
Bugzilla is at C<bugzilla.yourdomain.com>, then your REST client would
access the API via: C<http://bugzilla.yourdomain.com/rest/bug/35> which
looks cleaner.
=head1 BROWSING
If the Accept: header of a request is set to text/html (as it is by an
ordinary web browser) then the API will return the JSON data as a HTML
page which the browser can display. In other words, you can play with the
API using just your browser and see results in a human-readable form.
This is a good way to try out the various GET calls, even if you can't use
it for POST or PUT.
=head1 DATA FORMAT
The REST API only supports JSON input, and either JSON and JSONP output.
So objects sent and received must be in JSON format. Basically since
the REST API is a sub class of the JSONRPC API, you can refer to
L<JSONRPC|Bugzilla::WebService::Server::JSONRPC> for more information
on data types that are valid for REST.
On every request, you must set both the "Accept" and "Content-Type" HTTP
headers to the MIME type of the data format you are using to communicate with
the API. Content-Type tells the API how to interpret your request, and Accept
tells it how you want your data back. "Content-Type" must be "application/json".
"Accept" can be either that, or "application/javascript" for JSONP - add a "callback"
parameter to name your callback.
=head1 AUTHENTICATION
Along with viewing data as an anonymous user, you may also see private information
if you have a Bugzilla account by providing your login credentials.
=over
=item Username and password
Pass in as query parameters of any request:
username=fred@bedrock.com&password=ilovewilma
Remember to URL encode any special characters, which are often seen in passwords and to
also enable SSL support.
=back
=head1 ERRORS
When an error occurs over REST, a hash structure is returned with the key C<error>
set to C<true>.
The error contents look similar to:
{ "error": true, "message": "Some message here", "code": 123 }
Every error has a "code", as described in L<Bugzilla::WebService/ERRORS>.
Errors with a numeric C<code> higher than 100000 are errors thrown by
the JSON-RPC library that Bugzilla uses, not by Bugzilla.
=head1 UTILITY FUNCTIONS
=over
=item B<handle>
This method overrides the handle method provided by JSONRPC so that certain
actions related to REST such as determining the proper resource to use,
loading query parameters, etc. can be done before the proper WebService
method is executed.
=item B<response>
This method overrides the response method provided by JSONRPC so that
the response content can be altered for REST before being returned to
the client.
=item B<handle_login>
This method determines the proper WebService all to make based on class
and method name determined earlier. Then calls L<Bugzilla::WebService::Server::handle_login>
which will attempt to authenticate the client.
=item B<bz_method_name>
The WebService method name that matches the path used by the client.
=item B<bz_class_name>
The WebService class containing the method that matches the path used by the client.
=item B<bz_rest_params>
Each REST resource contains a hash key called C<params> that is a subroutine reference.
This subroutine will return a hash structure based on matched values from the path
information that is formatted properly for the WebService method that will be called.
=item B<bz_rest_options>
When a client uses the OPTIONS request method along with a specific path, they are
requesting the list of request methods that are valid for the path. Such as for the
path /bug, the valid request methods are GET (search) and POST (create). So the
client would receive in the response header, C<Access-Control-Allow-Methods: GET, POST>.
=item B<bz_success_code>
Each resource can specify a specific SUCCESS CODE if the operation completes successfully.
OTherwise STATUS OK (200) is the default returned.
=item B<rest_include_exclude>
Normally the WebService methods required C<include_fields> and C<exclude_fields> to be an
array of field names. REST allows for the values for these to be instead comma delimited
string of field names. This method converts the latter into the former so the WebService
methods will not complain.
=back
=head1 SEE ALSO
L<Bugzilla::WebService>
Bugzilla/WebService/Server/REST/Resources/Bug.pm
0 → 100644
View file @
384d1d25
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
package
Bugzilla::WebService::Server::REST::Resources::
Bug
;
use
5.10.1
;
use
strict
;
use
Bugzilla::WebService::
Constants
;
use
Bugzilla::WebService::
Bug
;
BEGIN
{
*
Bugzilla::WebService::Bug::
rest_resources
=
\&
_rest_resources
;
};
sub
_rest_resources
{
my
$rest_resources
=
[
qr{^/bug$}
,
{
GET
=>
{
method
=>
'search'
,
},
POST
=>
{
method
=>
'create'
,
status_code
=>
STATUS_CREATED
}
},
qr{^/bug/([^/]+)$}
,
{
GET
=>
{
method
=>
'get'
,
params
=>
sub
{
return
{
ids
=>
[
$_
[
0
]
]
};
}
},
PUT
=>
{
method
=>
'update'
,
params
=>
sub
{
return
{
ids
=>
[
$_
[
0
]
]
};
}
}
},
qr{^/bug/([^/]+)/comment$}
,
{
GET
=>
{
method
=>
'comments'
,
params
=>
sub
{
return
{
ids
=>
[
$_
[
0
]
]
};
}
},
POST
=>
{
method
=>
'add_comment'
,
params
=>
sub
{
return
{
id
=>
$_
[
0
]
};
},
success_code
=>
STATUS_CREATED
}
},
qr{^/bug/comment/([^/]+)$}
,
{
GET
=>
{
method
=>
'comments'
,
params
=>
sub
{
return
{
comment_ids
=>
[
$_
[
0
]
]
};
}
}
},
qr{^/bug/([^/]+)/history$}
,
{
GET
=>
{
method
=>
'history'
,
params
=>
sub
{
return
{
ids
=>
[
$_
[
0
]
]
};
},
}
},
qr{^/bug/([^/]+)/attachment$}
,
{
GET
=>
{
method
=>
'attachments'
,
params
=>
sub
{
return
{
ids
=>
[
$_
[
0
]
]
};
}
},
POST
=>
{
method
=>
'add_attachment'
,
params
=>
sub
{
return
{
ids
=>
[
$_
[
0
]
]
};
},
success_code
=>
STATUS_CREATED
}
},
qr{^/bug/attachment/([^/]+)$}
,
{
GET
=>
{
method
=>
'attachments'
,
params
=>
sub
{
return
{
attachment_ids
=>
[
$_
[
0
]
]
};
}
}
},
qr{^/field/bug$}
,
{
GET
=>
{
method
=>
'fields'
,
}
},
qr{^/field/bug/([^/]+)$}
,
{
GET
=>
{
method
=>
'fields'
,
params
=>
sub
{
my
$value
=
$_
[
0
];
my
$param
=
'names'
;
$param
=
'ids'
if
$value
=~
/^\d+$/
;
return
{
$param
=>
[
$_
[
0
]
]
};
}
}
},
qr{^/field/bug/([^/]+)/values$}
,
{
GET
=>
{
method
=>
'legal_values'
,
params
=>
sub
{
return
{
field
=>
$_
[
0
]
};
}
}
},
qr{^/field/bug/([^/]+)/([^/]+)/values$}
,
{
GET
=>
{
method
=>
'legal_values'
,
params
=>
sub
{
return
{
field
=>
$_
[
0
],
product_id
=>
$_
[
1
]
};
}
}
},
];
return
$rest_resources
;
}
1
;
__END__
=head1 NAME
Bugzilla::Webservice::Server::REST::Resources::Bug - The REST API for creating,
changing, and getting the details of bugs.
=head1 DESCRIPTION
This part of the Bugzilla REST API allows you to file a new bug in Bugzilla,
or get information about bugs that have already been filed.
See L<Bugzilla::WebService::Bug> for more details on how to use this part of
the REST API.
Bugzilla/WebService/Server/REST/Resources/Bugzilla.pm
0 → 100644
View file @
384d1d25
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
package
Bugzilla::WebService::Server::REST::Resources::
Bugzilla
;
use
5.10.1
;
use
strict
;
use
Bugzilla::WebService::
Constants
;
use
Bugzilla::WebService::
Bugzilla
;
BEGIN
{
*
Bugzilla::WebService::Bugzilla::
rest_resources
=
\&
_rest_resources
;
};
sub
_rest_resources
{
my
$rest_resources
=
[
qr{^/version$}
,
{
GET
=>
{
method
=>
'version'
}
},
qr{^/extensions$}
,
{
GET
=>
{
method
=>
'extensions'
}
},
qr{^/timezone$}
,
{
GET
=>
{
method
=>
'timezone'
}
},
qr{^/time$}
,
{
GET
=>
{
method
=>
'time'
}
},
qr{^/last_audit_time$}
,
{
GET
=>
{
method
=>
'last_audit_time'
}
},
qr{^/parameters$}
,
{
GET
=>
{
method
=>
'parameters'
}
}
];
return
$rest_resources
;
}
1
;
__END__
=head1 NAME
Bugzilla::WebService::Bugzilla - Global functions for the webservice interface.
=head1 DESCRIPTION
This provides functions that tell you about Bugzilla in general.
See L<Bugzilla::WebService::Bugzilla> for more details on how to use this part
of the REST API.
Bugzilla/WebService/Server/REST/Resources/Classification.pm
0 → 100644
View file @
384d1d25
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
package
Bugzilla::WebService::Server::REST::Resources::
Classification
;
use
5.10.1
;
use
strict
;
use
Bugzilla::WebService::
Constants
;
use
Bugzilla::WebService::
Classification
;
BEGIN
{
*
Bugzilla::WebService::Classification::
rest_resources
=
\&
_rest_resources
;
};
sub
_rest_resources
{
my
$rest_resources
=
[
qr{^/classification/([^/]+)$}
,
{
GET
=>
{
method
=>
'get'
,
params
=>
sub
{
my
$param
=
$_
[
0
]
=~
/^\d+$/
?
'ids'
:
'names'
;
return
{
$param
=>
[
$_
[
0
]
]
};
}
}
}
];
return
$rest_resources
;
}
1
;
__END__
=head1 NAME
Bugzilla::Webservice::Server::REST::Resources::Classification - The Classification REST API
=head1 DESCRIPTION
This part of the Bugzilla REST API allows you to deal with the available Classifications.
You will be able to get information about them as well as manipulate them.
See L<Bugzilla::WebService::Bug> for more details on how to use this part
of the REST API.
Bugzilla/WebService/Server/REST/Resources/Group.pm
0 → 100644
View file @
384d1d25
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
package
Bugzilla::WebService::Server::REST::Resources::
Group
;
use
5.10.1
;
use
strict
;
use
Bugzilla::WebService::
Constants
;
use
Bugzilla::WebService::
Group
;
BEGIN
{
*
Bugzilla::WebService::Group::
rest_resources
=
\&
_rest_resources
;
};
sub
_rest_resources
{
my
$rest_resources
=
[
qr{^/group$}
,
{
POST
=>
{
method
=>
'create'
,
success_code
=>
STATUS_CREATED
}
},
qr{^/group/([^/]+)$}
,
{
PUT
=>
{
method
=>
'update'
,
params
=>
sub
{
my
$param
=
$_
[
0
]
=~
/^\d+$/
?
'ids'
:
'names'
;
return
{
$param
=>
[
$_
[
0
]
]
};
}
}
}
];
return
$rest_resources
;
}
1
;
__END__
=head1 NAME
Bugzilla::Webservice::Server::REST::Resources::Group - The REST API for
creating, changing, and getting information about Groups.
=head1 DESCRIPTION
This part of the Bugzilla REST API allows you to create Groups and
get information about them.
See L<Bugzilla::WebService::Group> for more details on how to use this part
of the REST API.
Bugzilla/WebService/Server/REST/Resources/Product.pm
0 → 100644
View file @
384d1d25
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
package
Bugzilla::WebService::Server::REST::Resources::
Product
;
use
5.10.1
;
use
strict
;
use
Bugzilla::WebService::
Constants
;
use
Bugzilla::WebService::
Product
;
use
Bugzilla::
Error
;
BEGIN
{
*
Bugzilla::WebService::Product::
rest_resources
=
\&
_rest_resources
;
};
sub
_rest_resources
{
my
$rest_resources
=
[
qr{^/product$}
,
{
GET
=>
{
method
=>
sub
{
my
$type
=
Bugzilla
->
input_params
->
{
type
};
return
'get_accessible_products'
if
!
defined
$type
||
$type
eq
'accessible'
;
return
'get_enterable_products'
if
$type
eq
'enterable'
;
return
'get_selectable_products'
if
$type
eq
'selectable'
;
ThrowUserError
(
'rest_get_products_invalid_type'
,
{
type
=>
$type
});
},
},
POST
=>
{
method
=>
'create'
,
success_code
=>
STATUS_CREATED
}
},
qr{^/product/([^/]+)$}
,
{
GET
=>
{
method
=>
'get'
,
params
=>
sub
{
my
$param
=
$_
[
0
]
=~
/^\d+$/
?
'ids'
:
'names'
;
return
{
$param
=>
[
$_
[
0
]
]
};
}
},
PUT
=>
{
method
=>
'update'
,
params
=>
sub
{
my
$param
=
$_
[
0
]
=~
/^\d+$/
?
'ids'
:
'names'
;
return
{
$param
=>
[
$_
[
0
]
]
};
}
}
},
];
return
$rest_resources
;
}
1
;
__END__
=head1 NAME
Bugzilla::Webservice::Server::REST::Resources::Product - The Product REST API
=head1 DESCRIPTION
This part of the Bugzilla REST API allows you to list the available Products and
get information about them.
See L<Bugzilla::WebService::Bug> for more details on how to use this part of
the REST API.
Bugzilla/WebService/Server/REST/Resources/User.pm
0 → 100644
View file @
384d1d25
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
package
Bugzilla::WebService::Server::REST::Resources::
User
;
use
5.10.1
;
use
strict
;
use
Bugzilla::WebService::
Constants
;
use
Bugzilla::WebService::
User
;
BEGIN
{
*
Bugzilla::WebService::User::
rest_resources
=
\&
_rest_resources
;
};
sub
_rest_resources
{
my
$rest_resources
=
[
qr{^/user$}
,
{
GET
=>
{
method
=>
'get'
},
POST
=>
{
method
=>
'create'
,
success_code
=>
STATUS_CREATED
}
},
qr{^/user/([^/]+)$}
,
{
GET
=>
{
method
=>
'get'
,
params
=>
sub
{
my
$param
=
$_
[
0
]
=~
/^\d+$/
?
'ids'
:
'names'
;
return
{
$param
=>
[
$_
[
0
]
]
};
}
},
PUT
=>
{
method
=>
'update'
,
params
=>
sub
{
my
$param
=
$_
[
0
]
=~
/^\d+$/
?
'ids'
:
'names'
;
return
{
$param
=>
[
$_
[
0
]
]
};
}
}
}
];
return
$rest_resources
;
}
1
;
__END__
=head1 NAME
Bugzilla::Webservice::Server::REST::Resources::User - The User Account REST API
=head1 DESCRIPTION
This part of the Bugzilla REST API allows you to get User information as well
as create User Accounts.
See L<Bugzilla::WebService::Bug> for more details on how to use this part of
the REST API.
Bugzilla/WebService/User.pm
View file @
384d1d25
...
...
@@ -127,7 +127,7 @@ sub create {
# $call = $rpc->call( 'User.get', { ids => [1,2,3],
# names => ['testusera@redhat.com', 'testuserb@redhat.com'] });
sub
get
{
my
(
$self
,
$params
)
=
validate
(
@_
,
'names'
,
'ids'
);
my
(
$self
,
$params
)
=
validate
(
@_
,
'names'
,
'ids'
,
'match'
,
'group_ids'
,
'groups'
);
Bugzilla
->
switch_to_shadow_db
();
...
...
@@ -399,6 +399,10 @@ log in/out using an existing account.
See L<Bugzilla::WebService> for a description of how parameters are passed,
and what B<STABLE>, B<UNSTABLE>, and B<EXPERIMENTAL> mean.
Although the data input and output is the same for JSONRPC, XMLRPC and REST,
the directions for how to access the data via REST is noted in each method
where applicable.
=head1 Logging In and Out
=head2 login
...
...
@@ -541,6 +545,13 @@ actually receive an email. This function does not check that.
You must be logged in and have the C<editusers> privilege in order to
call this function.
=item B<REST>
POST /user
The params to include in the POST body as well as the returned data format,
are the same as below.
=item B<Params>
=over
...
...
@@ -584,6 +595,8 @@ password is under three characters.)
=item Error 503 (Password Too Long) removed in Bugzilla B<3.6>.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
...
...
@@ -598,6 +611,14 @@ B<EXPERIMENTAL>
Updates user accounts in Bugzilla.
=item B<REST>
PUT /user/<user_id_or_name>
The params to include in the PUT body as well as the returned data format,
are the same as below. The C<ids> and C<names> params are overridden as they
are pulled from the URL path.
=item B<Params>
=over
...
...
@@ -684,6 +705,14 @@ Logged-in users are not authorized to edit other users.
=back
=item B<History>
=over
=item REST API call added in Bugzilla B<5.0>.
=back
=back
=head1 User Info
...
...
@@ -698,6 +727,18 @@ B<STABLE>
Gets information about user accounts in Bugzilla.
=item B<REST>
To get information about a single user:
GET /user/<user_id_or_name>
To search for users by name, group using URL params same as below:
GET /user
The returned data format is the same as below.
=item B<Params>
B<Note>: At least one of C<ids>, C<names>, or C<match> must be specified.
...
...
@@ -920,6 +961,8 @@ illegal to pass a group name you don't belong to.
=item C<groups>, C<saved_searches>, and C<saved_reports> were added
in Bugzilla B<4.4>.
=item REST API call added in Bugzilla B<5.0>.
=back
=back
rest.cgi
0 → 100755
View file @
384d1d25
#!/usr/bin/perl -wT
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use
5.10.1
;
use
strict
;
use
lib
qw(. lib)
;
use
Bugzilla
;
use
Bugzilla::
Constants
;
use
Bugzilla::
Error
;
use
Bugzilla::WebService::
Constants
;
BEGIN
{
if
(
!
Bugzilla
->
feature
(
'rest'
)
||
!
Bugzilla
->
feature
(
'jsonrpc'
))
{
ThrowUserError
(
'feature_disabled'
,
{
feature
=>
'rest'
});
}
}
use
Bugzilla::WebService::Server::
REST
;
Bugzilla
->
usage_mode
(
USAGE_MODE_REST
);
local
@INC
=
(
bz_locations
()
->
{
extensionsdir
},
@INC
);
my
$server
=
new
Bugzilla::WebService::Server::
REST
;
$server
->
version
(
'1.1'
);
$server
->
handle
();
template/en/default/global/user-error.html.tmpl
View file @
384d1d25
...
...
@@ -1073,6 +1073,13 @@
For security reasons, you must use HTTP POST to call the
'[% method FILTER html %]' method.
[% ELSIF error == "rest_invalid_resource" %]
A REST API resource was not found for '[% method FILTER html +%] [%+ path FILTER html %]'.
[% ELSIF error == "rest_get_products_invalid_type" %]
The type '[% type FILTER html %]' is invalid for 'GET /product'. Valid choices
are 'accessible' (default if type value is undefined), 'selectable', and 'enterable'.
[% ELSIF error == "keyword_already_exists" %]
[% title = "Keyword Already Exists" %]
A keyword with the name [% name FILTER html %] already exists.
...
...
template/en/default/rest.html.tmpl
0 → 100644
View file @
384d1d25
[%# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
#%]
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>
Bugzilla::REST::API
</title>
<link
href=
"[% urlbase FILTER none %][% 'skins/standard/global.css' FILTER mtime %]"
rel=
"stylesheet"
type=
"text/css"
>
</head>
<body>
<pre>
[% result FILTER html %]
</pre>
</body>
</html>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment