Standardize REST endpoints for getting changes
The /detail and /review endpoints are practically identical to the standard change endpoint except for the default set of options. Make this equivalence explicit in the code by delegating to a GetChange instance from the other handlers. This change naturally gets caching for the other endpoints as well. Allow specifying options on /change/X; prior to this, users could add options to the default set from /detail but could not remove options. Change-Id: I03bb96141e79ae00359f8d5ec51413d1b27204dc
This commit is contained in:
@@ -336,6 +336,11 @@ Get Change
|
|||||||
|
|
||||||
Retrieves a change.
|
Retrieves a change.
|
||||||
|
|
||||||
|
Additional fields can be obtained by adding `o` parameters, each
|
||||||
|
option requires more database lookups and slows down the query
|
||||||
|
response time to the client so they are generally disabled by
|
||||||
|
default. Fields are described in link:#list-changes[Query Changes].
|
||||||
|
|
||||||
.Request
|
.Request
|
||||||
----
|
----
|
||||||
GET /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940 HTTP/1.0
|
GET /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940 HTTP/1.0
|
||||||
|
|||||||
@@ -14,13 +14,30 @@
|
|||||||
|
|
||||||
package com.google.gerrit.server.change;
|
package com.google.gerrit.server.change;
|
||||||
|
|
||||||
|
import com.google.gerrit.common.changes.ListChangesOption;
|
||||||
|
import com.google.gerrit.extensions.restapi.CacheControl;
|
||||||
|
import com.google.gerrit.extensions.restapi.Response;
|
||||||
import com.google.gerrit.extensions.restapi.RestReadView;
|
import com.google.gerrit.extensions.restapi.RestReadView;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
|
import org.kohsuke.args4j.Option;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class GetChange implements RestReadView<ChangeResource> {
|
public class GetChange implements RestReadView<ChangeResource> {
|
||||||
private final ChangeJson json;
|
private final ChangeJson json;
|
||||||
|
|
||||||
|
@Option(name = "-o", multiValued = true, usage = "Output options")
|
||||||
|
void addOption(ListChangesOption o) {
|
||||||
|
json.addOption(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Option(name = "-O", usage = "Output option flags, in hex")
|
||||||
|
void setOptionFlagsHex(String hex) {
|
||||||
|
json.addOptions(ListChangesOption.fromBits(Integer.parseInt(hex, 16)));
|
||||||
|
}
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
GetChange(ChangeJson json) {
|
GetChange(ChangeJson json) {
|
||||||
this.json = json;
|
this.json = json;
|
||||||
@@ -28,6 +45,15 @@ public class GetChange implements RestReadView<ChangeResource> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object apply(ChangeResource rsrc) throws OrmException {
|
public Object apply(ChangeResource rsrc) throws OrmException {
|
||||||
return json.format(rsrc);
|
return cache(json.format(rsrc));
|
||||||
|
}
|
||||||
|
|
||||||
|
Object apply(RevisionResource rsrc) throws OrmException {
|
||||||
|
return cache(json.format(rsrc));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object cache(Object res) {
|
||||||
|
return Response.ok(res)
|
||||||
|
.caching(CacheControl.PRIVATE(0, TimeUnit.SECONDS).setMustRevalidate());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,41 +15,36 @@
|
|||||||
package com.google.gerrit.server.change;
|
package com.google.gerrit.server.change;
|
||||||
|
|
||||||
import com.google.gerrit.common.changes.ListChangesOption;
|
import com.google.gerrit.common.changes.ListChangesOption;
|
||||||
import com.google.gerrit.extensions.restapi.CacheControl;
|
|
||||||
import com.google.gerrit.extensions.restapi.Response;
|
|
||||||
import com.google.gerrit.extensions.restapi.RestReadView;
|
import com.google.gerrit.extensions.restapi.RestReadView;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
import org.kohsuke.args4j.Option;
|
import org.kohsuke.args4j.Option;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
public class GetDetail implements RestReadView<ChangeResource> {
|
public class GetDetail implements RestReadView<ChangeResource> {
|
||||||
private final ChangeJson json;
|
private final GetChange delegate;
|
||||||
|
|
||||||
@Option(name = "-o", multiValued = true, usage = "Output options")
|
@Option(name = "-o", multiValued = true, usage = "Output options")
|
||||||
void addOption(ListChangesOption o) {
|
void addOption(ListChangesOption o) {
|
||||||
json.addOption(o);
|
delegate.addOption(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Option(name = "-O", usage = "Output option flags, in hex")
|
@Option(name = "-O", usage = "Output option flags, in hex")
|
||||||
void setOptionFlagsHex(String hex) {
|
void setOptionFlagsHex(String hex) {
|
||||||
json.addOptions(ListChangesOption.fromBits(Integer.parseInt(hex, 16)));
|
delegate.setOptionFlagsHex(hex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
GetDetail(ChangeJson json) {
|
GetDetail(GetChange delegate) {
|
||||||
this.json = json
|
this.delegate = delegate;
|
||||||
.addOption(ListChangesOption.LABELS)
|
delegate.addOption(ListChangesOption.LABELS);
|
||||||
.addOption(ListChangesOption.DETAILED_LABELS)
|
delegate.addOption(ListChangesOption.DETAILED_LABELS);
|
||||||
.addOption(ListChangesOption.DETAILED_ACCOUNTS)
|
delegate.addOption(ListChangesOption.DETAILED_ACCOUNTS);
|
||||||
.addOption(ListChangesOption.MESSAGES);
|
delegate.addOption(ListChangesOption.MESSAGES);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object apply(ChangeResource rsrc) throws OrmException {
|
public Object apply(ChangeResource rsrc) throws OrmException {
|
||||||
return Response.ok(json.format(rsrc))
|
return delegate.apply(rsrc);
|
||||||
.caching(CacheControl.PRIVATE(0, TimeUnit.SECONDS).setMustRevalidate());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,17 +20,17 @@ import com.google.gwtorm.server.OrmException;
|
|||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
public class GetReview implements RestReadView<RevisionResource> {
|
public class GetReview implements RestReadView<RevisionResource> {
|
||||||
private final ChangeJson json;
|
private final GetChange delegate;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
GetReview(ChangeJson json) {
|
GetReview(GetChange delegate) {
|
||||||
this.json = json
|
this.delegate = delegate;
|
||||||
.addOption(ListChangesOption.DETAILED_LABELS)
|
delegate.addOption(ListChangesOption.DETAILED_LABELS);
|
||||||
.addOption(ListChangesOption.DETAILED_ACCOUNTS);
|
delegate.addOption(ListChangesOption.DETAILED_ACCOUNTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object apply(RevisionResource resource) throws OrmException {
|
public Object apply(RevisionResource rsrc) throws OrmException {
|
||||||
return json.format(resource);
|
return delegate.apply(rsrc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
package com.google.gerrit.server.change;
|
package com.google.gerrit.server.change;
|
||||||
|
|
||||||
import com.google.gerrit.extensions.restapi.RestResource;
|
import com.google.gerrit.extensions.restapi.RestResource;
|
||||||
|
import com.google.gerrit.extensions.restapi.RestResource.HasETag;
|
||||||
import com.google.gerrit.extensions.restapi.RestView;
|
import com.google.gerrit.extensions.restapi.RestView;
|
||||||
import com.google.gerrit.reviewdb.client.Account;
|
import com.google.gerrit.reviewdb.client.Account;
|
||||||
import com.google.gerrit.reviewdb.client.Change;
|
import com.google.gerrit.reviewdb.client.Change;
|
||||||
@@ -23,7 +24,7 @@ import com.google.gerrit.server.IdentifiedUser;
|
|||||||
import com.google.gerrit.server.project.ChangeControl;
|
import com.google.gerrit.server.project.ChangeControl;
|
||||||
import com.google.inject.TypeLiteral;
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
public class RevisionResource implements RestResource {
|
public class RevisionResource implements RestResource, HasETag {
|
||||||
public static final TypeLiteral<RestView<RevisionResource>> REVISION_KIND =
|
public static final TypeLiteral<RestView<RevisionResource>> REVISION_KIND =
|
||||||
new TypeLiteral<RestView<RevisionResource>>() {};
|
new TypeLiteral<RestView<RevisionResource>>() {};
|
||||||
|
|
||||||
@@ -56,6 +57,14 @@ public class RevisionResource implements RestResource {
|
|||||||
return ps;
|
return ps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getETag() {
|
||||||
|
// Conservative estimate: refresh the revision if its parent change has
|
||||||
|
// changed, so we don't have to check whether a given modification affected
|
||||||
|
// this revision specifically.
|
||||||
|
return change.getETag();
|
||||||
|
}
|
||||||
|
|
||||||
Account.Id getAccountId() {
|
Account.Id getAccountId() {
|
||||||
return getUser().getAccountId();
|
return getUser().getAccountId();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user