summaryrefslogtreecommitdiffstats
path: root/Bugzilla/WebService/Server
diff options
context:
space:
mode:
authorDave Lawrence <dlawrence@mozilla.com>2013-08-09 19:10:51 +0200
committerDave Lawrence <dlawrence@mozilla.com>2013-08-09 19:10:51 +0200
commit37ce30c4eabef0d10e3bfdff0ee9669f6fe5c7df (patch)
tree2fb75ca52ed0ba0285db69ccee064ebfbeb3be40 /Bugzilla/WebService/Server
parentc1a59a49a014f332793bbc9b3bea8717718428e5 (diff)
downloadbugzilla-37ce30c4eabef0d10e3bfdff0ee9669f6fe5c7df.tar.gz
bugzilla-37ce30c4eabef0d10e3bfdff0ee9669f6fe5c7df.tar.xz
Bug 569177 - Add support for eTag for WebServices
r/a=glob
Diffstat (limited to 'Bugzilla/WebService/Server')
-rw-r--r--Bugzilla/WebService/Server/JSONRPC.pm29
-rw-r--r--Bugzilla/WebService/Server/REST.pm4
-rw-r--r--Bugzilla/WebService/Server/XMLRPC.pm27
3 files changed, 52 insertions, 8 deletions
diff --git a/Bugzilla/WebService/Server/JSONRPC.pm b/Bugzilla/WebService/Server/JSONRPC.pm
index d4573fd19..e7b3fe7e7 100644
--- a/Bugzilla/WebService/Server/JSONRPC.pm
+++ b/Bugzilla/WebService/Server/JSONRPC.pm
@@ -75,12 +75,12 @@ sub response_header {
sub response {
my ($self, $response) = @_;
+ my $cgi = $self->cgi;
# 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.
@@ -95,9 +95,18 @@ sub response {
push(@header_args, "-$name", $value);
}
}
- my $cgi = $self->cgi;
- print $cgi->header(-status => $response->code, @header_args);
- print $response->content;
+
+ # ETag support
+ my $etag = $self->bz_etag;
+ if ($etag && $cgi->check_etag($etag)) {
+ push(@header_args, "-ETag", $etag);
+ print $cgi->header(-status => '304 Not Modified', @header_args);
+ }
+ else {
+ push(@header_args, "-ETag", $etag) if $etag;
+ print $cgi->header(-status => $response->code, @header_args);
+ print $response->content;
+ }
}
# The JSON-RPC 1.1 GET specification is not so great--you can't specify
@@ -257,7 +266,17 @@ sub _handle {
my $self = shift;
my ($obj) = @_;
$self->{_bz_request_id} = $obj->{id};
- return $self->SUPER::_handle(@_);
+
+ my $result = $self->SUPER::_handle(@_);
+
+ # Set the ETag if not already set in the webservice methods.
+ my $etag = $self->bz_etag;
+ if (!$etag && ref $result) {
+ my $data = $self->json->decode($result)->{'result'};
+ $self->bz_etag($data);
+ }
+
+ return $result;
}
# Make all error messages returned by JSON::RPC go into the 100000
diff --git a/Bugzilla/WebService/Server/REST.pm b/Bugzilla/WebService/Server/REST.pm
index 00c71110f..8d3aa481c 100644
--- a/Bugzilla/WebService/Server/REST.pm
+++ b/Bugzilla/WebService/Server/REST.pm
@@ -125,6 +125,10 @@ sub response {
# Access Control
$response->header("Access-Control-Allow-Origin", "*");
+ # ETag support
+ my $etag = $self->bz_etag;
+ $self->bz_etag($result) if !$etag;
+
# If accessing through web browser, then display in readable format
if ($self->content_type eq 'text/html') {
$result = $self->json->pretty->canonical->encode($result);
diff --git a/Bugzilla/WebService/Server/XMLRPC.pm b/Bugzilla/WebService/Server/XMLRPC.pm
index 93c9b4cdc..40c66a8f9 100644
--- a/Bugzilla/WebService/Server/XMLRPC.pm
+++ b/Bugzilla/WebService/Server/XMLRPC.pm
@@ -21,8 +21,8 @@ if ($ENV{MOD_PERL}) {
use Bugzilla::WebService::Constants;
use Bugzilla::Util;
-# Allow WebService methods to call XMLRPC::Lite's type method directly
BEGIN {
+ # Allow WebService methods to call XMLRPC::Lite's type method directly
*Bugzilla::WebService::type = sub {
my ($self, $type, $value) = @_;
if ($type eq 'dateTime') {
@@ -39,6 +39,11 @@ BEGIN {
}
return XMLRPC::Data->type($type)->value($value);
};
+
+ # Add support for ETags into XMLRPC WebServices
+ *Bugzilla::WebService::bz_etag = sub {
+ return Bugzilla::WebService::Server->bz_etag($_[1]);
+ };
}
sub initialize {
@@ -52,22 +57,38 @@ sub initialize {
sub make_response {
my $self = shift;
+ my $cgi = Bugzilla->cgi;
$self->SUPER::make_response(@_);
# XMLRPC::Transport::HTTP::CGI doesn't know about Bugzilla carrying around
# its cookies in Bugzilla::CGI, so we need to copy them over.
- foreach my $cookie (@{Bugzilla->cgi->{'Bugzilla_cookie_list'}}) {
+ foreach my $cookie (@{$cgi->{'Bugzilla_cookie_list'}}) {
$self->response->headers->push_header('Set-Cookie', $cookie);
}
# Copy across security related headers from Bugzilla::CGI
- foreach my $header (split(/[\r\n]+/, Bugzilla->cgi->header)) {
+ foreach my $header (split(/[\r\n]+/, $cgi->header)) {
my ($name, $value) = $header =~ /^([^:]+): (.*)/;
if (!$self->response->headers->header($name)) {
$self->response->headers->header($name => $value);
}
}
+
+ # ETag support
+ my $etag = $self->bz_etag;
+ if (!$etag) {
+ my $data = $self->response->as_string;
+ $etag = $self->bz_etag($data);
+ }
+
+ if ($etag && $cgi->check_etag($etag)) {
+ $self->response->headers->push_header('ETag', $etag);
+ $self->response->headers->push_header('status', '304 Not Modified');
+ }
+ elsif ($etag) {
+ $self->response->headers->push_header('ETag', $etag);
+ }
}
sub handle_login {