Revert "Consistently construct RestApi without leading and trailing slashes"
This change e.g. broke listing of changes in the UI. This is because
REST root collections require a trailing slash. Otherwise the request
fails with '404 Not Found'.
This reverts commit c67893ae6a.
Change-Id: I874ca2f593e901ab157f1e61031f632a8b8007ab
			
			
This commit is contained in:
		| @@ -101,7 +101,7 @@ public class AvatarImage extends Image implements LoadHandler { | ||||
|         && u.equals(Gerrit.getUserAccount().email())) { | ||||
|       u = "self"; | ||||
|     } | ||||
|     RestApi api = new RestApi("accounts").id(u).view("avatar"); | ||||
|     RestApi api = new RestApi("/accounts/").id(u).view("avatar"); | ||||
|     if (size > 0) { | ||||
|       api.addParameter("s", size); | ||||
|       setSize("", size + "px"); | ||||
|   | ||||
| @@ -26,7 +26,7 @@ import java.util.Set; | ||||
| public class AccessMap extends NativeMap<ProjectAccessInfo> { | ||||
|   public static void get(Set<Project.NameKey> projects, | ||||
|       AsyncCallback<AccessMap> callback) { | ||||
|     RestApi api = new RestApi("access"); | ||||
|     RestApi api = new RestApi("/access/"); | ||||
|     for (Project.NameKey p : projects) { | ||||
|       api.addParameter("project", p.get()); | ||||
|     } | ||||
|   | ||||
| @@ -35,7 +35,7 @@ import java.util.Set; | ||||
|  */ | ||||
| public class AccountApi { | ||||
|   public static RestApi self() { | ||||
|     return accounts().view("self"); | ||||
|     return new RestApi("/accounts/").view("self"); | ||||
|   } | ||||
|  | ||||
|   /** Retrieve the account edit preferences */ | ||||
| @@ -51,7 +51,7 @@ public class AccountApi { | ||||
|  | ||||
|   public static void suggest(String query, int limit, | ||||
|       AsyncCallback<JsArray<AccountInfo>> cb) { | ||||
|     accounts() | ||||
|     new RestApi("/accounts/") | ||||
|       .addParameter("q", query) | ||||
|       .addParameter("n", limit) | ||||
|       .background() | ||||
| @@ -65,7 +65,7 @@ public class AccountApi { | ||||
|  | ||||
|   /** Retrieve the username */ | ||||
|   public static void getUsername(String account, AsyncCallback<NativeString> cb) { | ||||
|     accounts().id(account).view("username").get(cb); | ||||
|     new RestApi("/accounts/").id(account).view("username").get(cb); | ||||
|   } | ||||
|  | ||||
|   /** Set the username */ | ||||
| @@ -73,33 +73,33 @@ public class AccountApi { | ||||
|       AsyncCallback<NativeString> cb) { | ||||
|     UsernameInput input = UsernameInput.create(); | ||||
|     input.username(username); | ||||
|     accounts().id(account).view("username").put(input, cb); | ||||
|     new RestApi("/accounts/").id(account).view("username").put(input, cb); | ||||
|   } | ||||
|  | ||||
|   /** Retrieve email addresses */ | ||||
|   public static void getEmails(String account, | ||||
|       AsyncCallback<JsArray<EmailInfo>> cb) { | ||||
|     accounts().id(account).view("emails").get(cb); | ||||
|     new RestApi("/accounts/").id(account).view("emails").get(cb); | ||||
|   } | ||||
|  | ||||
|   /** Register a new email address */ | ||||
|   public static void registerEmail(String account, String email, | ||||
|       AsyncCallback<EmailInfo> cb) { | ||||
|     JavaScriptObject in = JavaScriptObject.createObject(); | ||||
|     accounts().id(account).view("emails").id(email) | ||||
|     new RestApi("/accounts/").id(account).view("emails").id(email) | ||||
|         .ifNoneMatch().put(in, cb); | ||||
|   } | ||||
|  | ||||
|   /** Retrieve SSH keys */ | ||||
|   public static void getSshKeys(String account, | ||||
|       AsyncCallback<JsArray<SshKeyInfo>> cb) { | ||||
|     accounts().id(account).view("sshkeys").get(cb); | ||||
|     new RestApi("/accounts/").id(account).view("sshkeys").get(cb); | ||||
|   } | ||||
|  | ||||
|   /** Add a new SSH keys */ | ||||
|   public static void addSshKey(String account, String sshPublicKey, | ||||
|       AsyncCallback<SshKeyInfo> cb) { | ||||
|     accounts().id(account).view("sshkeys") | ||||
|     new RestApi("/accounts/").id(account).view("sshkeys") | ||||
|         .post(sshPublicKey, cb); | ||||
|   } | ||||
|  | ||||
| @@ -114,7 +114,7 @@ public class AccountApi { | ||||
|       Set<Integer> sequenceNumbers, AsyncCallback<VoidResult> cb) { | ||||
|     CallbackGroup group = new CallbackGroup(); | ||||
|     for (int seq : sequenceNumbers) { | ||||
|       accounts().id(account).view("sshkeys").id(seq) | ||||
|       new RestApi("/accounts/").id(account).view("sshkeys").id(seq) | ||||
|           .delete(group.add(cb)); | ||||
|       cb = CallbackGroup.emptyCallback(); | ||||
|     } | ||||
| @@ -124,7 +124,7 @@ public class AccountApi { | ||||
|   /** Retrieve the HTTP password */ | ||||
|   public static void getHttpPassword(String account, | ||||
|       AsyncCallback<NativeString> cb) { | ||||
|     accounts().id(account).view("password.http").get(cb); | ||||
|     new RestApi("/accounts/").id(account).view("password.http").get(cb); | ||||
|   } | ||||
|  | ||||
|   /** Generate a new HTTP password */ | ||||
| @@ -132,13 +132,13 @@ public class AccountApi { | ||||
|       AsyncCallback<NativeString> cb) { | ||||
|     HttpPasswordInput in = HttpPasswordInput.create(); | ||||
|     in.generate(true); | ||||
|     accounts().id(account).view("password.http").put(in, cb); | ||||
|     new RestApi("/accounts/").id(account).view("password.http").put(in, cb); | ||||
|   } | ||||
|  | ||||
|   /** Clear HTTP password */ | ||||
|   public static void clearHttpPassword(String account, | ||||
|       AsyncCallback<VoidResult> cb) { | ||||
|     accounts().id(account).view("password.http").delete(cb); | ||||
|     new RestApi("/accounts/").id(account).view("password.http").delete(cb); | ||||
|   } | ||||
|  | ||||
|   private static class HttpPasswordInput extends JavaScriptObject { | ||||
| @@ -165,7 +165,7 @@ public class AccountApi { | ||||
|  | ||||
|   public static void addGpgKey(String account, String armored, | ||||
|       AsyncCallback<NativeMap<GpgKeyInfo>> cb) { | ||||
|     accounts() | ||||
|     new RestApi("/accounts/") | ||||
|       .id(account) | ||||
|       .view("gpgkeys") | ||||
|       .post(GpgKeysInput.add(armored), cb); | ||||
| @@ -173,16 +173,12 @@ public class AccountApi { | ||||
|  | ||||
|   public static void deleteGpgKeys(String account, | ||||
|       Iterable<String> fingerprints, AsyncCallback<NativeMap<GpgKeyInfo>> cb) { | ||||
|     accounts() | ||||
|     new RestApi("/accounts/") | ||||
|       .id(account) | ||||
|       .view("gpgkeys") | ||||
|       .post(GpgKeysInput.delete(fingerprints), cb); | ||||
|   } | ||||
|  | ||||
|   private static RestApi accounts() { | ||||
|     return new RestApi("accounts"); | ||||
|   } | ||||
|  | ||||
|   private static class GpgKeysInput extends JavaScriptObject { | ||||
|     static GpgKeysInput add(String key) { | ||||
|       return createWithAdd(Natives.arrayOf(key)); | ||||
|   | ||||
| @@ -21,7 +21,7 @@ import com.google.gwt.user.client.rpc.AsyncCallback; | ||||
| /** Capabilities the caller has from {@code /accounts/self/capabilities}.  */ | ||||
| public class AccountCapabilities extends JavaScriptObject { | ||||
|   public static void all(AsyncCallback<AccountCapabilities> cb, String... filter) { | ||||
|     new RestApi("accounts/self/capabilities") | ||||
|     new RestApi("/accounts/self/capabilities") | ||||
|       .addParameter("q", filter) | ||||
|       .get(cb); | ||||
|   } | ||||
|   | ||||
| @@ -100,7 +100,7 @@ public class MyProfileScreen extends SettingsScreen { | ||||
|   void display(AccountInfo account) { | ||||
|     if (Gerrit.info().plugin().hasAvatars()) { | ||||
|       avatar.setAccount(account, 93, false); | ||||
|       new RestApi("accounts").id("self").view("avatar.change.url") | ||||
|       new RestApi("/accounts/").id("self").view("avatar.change.url") | ||||
|           .get(new AsyncCallback<NativeString>() { | ||||
|             @Override | ||||
|             public void onSuccess(NativeString changeUrl) { | ||||
|   | ||||
| @@ -135,7 +135,7 @@ class DownloadBox extends VerticalPanel { | ||||
|   private void insertPatch() { | ||||
|     String id = revision.substring(0, 7); | ||||
|     Anchor patchBase64 = new Anchor(id + ".diff.base64"); | ||||
|     patchBase64.setHref(new RestApi("changes") | ||||
|     patchBase64.setHref(new RestApi("/changes/") | ||||
|       .id(psId.getParentKey().get()) | ||||
|       .view("revisions") | ||||
|       .id(revision) | ||||
| @@ -144,7 +144,7 @@ class DownloadBox extends VerticalPanel { | ||||
|       .url()); | ||||
|  | ||||
|     Anchor patchZip = new Anchor(id + ".diff.zip"); | ||||
|     patchZip.setHref(new RestApi("changes") | ||||
|     patchZip.setHref(new RestApi("/changes/") | ||||
|       .id(psId.getParentKey().get()) | ||||
|       .view("revisions") | ||||
|       .id(revision) | ||||
| @@ -170,7 +170,7 @@ class DownloadBox extends VerticalPanel { | ||||
|     List<Anchor> anchors = new ArrayList<>(activated.size()); | ||||
|     for (String f : activated) { | ||||
|       Anchor archive = new Anchor(f); | ||||
|       archive.setHref(new RestApi("changes") | ||||
|       archive.setHref(new RestApi("/changes/") | ||||
|           .id(psId.getParentKey().get()) | ||||
|           .view("revisions") | ||||
|           .id(revision) | ||||
|   | ||||
| @@ -59,7 +59,7 @@ public class ChangeApi { | ||||
|       input.status(Change.Status.DRAFT.toString()); | ||||
|     } | ||||
|  | ||||
|     new RestApi("changes").post(input, cb); | ||||
|     new RestApi("/changes/").post(input, cb); | ||||
|   } | ||||
|  | ||||
|   /** Restore a previously abandoned change to be open again. */ | ||||
| @@ -308,7 +308,7 @@ public class ChangeApi { | ||||
|  | ||||
|   public static RestApi change(int id) { | ||||
|     // TODO Switch to triplet project~branch~id format in URI. | ||||
|     return new RestApi("changes").id(String.valueOf(id)); | ||||
|     return new RestApi("/changes/").id(String.valueOf(id)); | ||||
|   } | ||||
|  | ||||
|   public static String emptyToNull(String str) { | ||||
|   | ||||
| @@ -25,7 +25,7 @@ import java.util.Set; | ||||
|  | ||||
| /** List of changes available from {@code /changes/}. */ | ||||
| public class ChangeList extends JsArray<ChangeInfo> { | ||||
|   private static final String URI = "changes"; | ||||
|   private static final String URI = "/changes/"; | ||||
|  | ||||
|   /** Run multiple queries in a single remote invocation. */ | ||||
|   public static void queryMultiple( | ||||
|   | ||||
| @@ -30,25 +30,25 @@ import com.google.gwt.user.client.rpc.AsyncCallback; | ||||
| public class ConfigServerApi { | ||||
|   /** map of the server wide capabilities (core & plugins). */ | ||||
|   public static void capabilities(AsyncCallback<NativeMap<CapabilityInfo>> cb) { | ||||
|     new RestApi("config/server/capabilities").get(cb); | ||||
|     new RestApi("/config/server/capabilities/").get(cb); | ||||
|   } | ||||
|  | ||||
|   public static void topMenus(AsyncCallback<TopMenuList> cb) { | ||||
|     new RestApi("config/server/top-menus").get(cb); | ||||
|     new RestApi("/config/server/top-menus").get(cb); | ||||
|   } | ||||
|  | ||||
|   public static void defaultPreferences(AsyncCallback<AccountPreferencesInfo> cb) { | ||||
|     new RestApi("config/server/preferences").get(cb); | ||||
|     new RestApi("/config/server/preferences").get(cb); | ||||
|   } | ||||
|  | ||||
|   public static void serverInfo(AsyncCallback<ServerInfo> cb) { | ||||
|     new RestApi("config/server/info").get(cb); | ||||
|     new RestApi("/config/server/info").get(cb); | ||||
|   } | ||||
|  | ||||
|   public static void confirmEmail(String token, AsyncCallback<VoidResult> cb) { | ||||
|     EmailConfirmationInput input = EmailConfirmationInput.create(); | ||||
|     input.setToken(token); | ||||
|     new RestApi("config/server/email.confirm").put(input, cb); | ||||
|     new RestApi("/config/server/email.confirm").put(input, cb); | ||||
|   } | ||||
|  | ||||
|   private static class EmailConfirmationInput extends JavaScriptObject { | ||||
|   | ||||
| @@ -38,7 +38,7 @@ public class DashboardList extends JsArray<DashboardInfo> { | ||||
|   } | ||||
|  | ||||
|   private static RestApi base(Project.NameKey project) { | ||||
|     return new RestApi("projects").id(project.get()).view("dashboards"); | ||||
|     return new RestApi("/projects/").id(project.get()).view("dashboards"); | ||||
|   } | ||||
|  | ||||
|   private static String encodeDashboardId(String id) { | ||||
|   | ||||
| @@ -22,6 +22,8 @@ import com.google.gwt.user.client.rpc.AsyncCallback; | ||||
| import com.google.gwtorm.client.KeyUtil; | ||||
|  | ||||
| public class DocScreen extends Screen { | ||||
|   private static final String URI = "/Documentation/"; | ||||
|  | ||||
|   private DocTable table; | ||||
|   private final String query; | ||||
|  | ||||
| @@ -69,7 +71,7 @@ public class DocScreen extends Screen { | ||||
|   } | ||||
|  | ||||
|   private void doQuery() { | ||||
|     RestApi call = new RestApi("Documentation"); | ||||
|     RestApi call = new RestApi(URI); | ||||
|     call.addParameterRaw("q", KeyUtil.encode(query)); | ||||
|     call.get(loadCallback()); | ||||
|   } | ||||
|   | ||||
| @@ -34,7 +34,7 @@ public class GroupApi { | ||||
|   /** Create a new group */ | ||||
|   public static void createGroup(String groupName, AsyncCallback<GroupInfo> cb) { | ||||
|     JavaScriptObject in = JavaScriptObject.createObject(); | ||||
|     new RestApi("groups").id(groupName).ifNoneMatch().put(in, cb); | ||||
|     new RestApi("/groups/").id(groupName).ifNoneMatch().put(in, cb); | ||||
|   } | ||||
|  | ||||
|   public static void getGroupDetail(String group, AsyncCallback<GroupInfo> cb) { | ||||
| @@ -212,7 +212,7 @@ public class GroupApi { | ||||
|   } | ||||
|  | ||||
|   private static RestApi group(String group) { | ||||
|     return new RestApi("groups").id(group); | ||||
|     return new RestApi("/groups/").id(group); | ||||
|   } | ||||
|  | ||||
|   private static class GroupInput extends JavaScriptObject { | ||||
|   | ||||
| @@ -22,12 +22,12 @@ import com.google.gwt.user.client.rpc.AsyncCallback; | ||||
| /** Groups available from {@code /groups/} or {@code /accounts/[id]/groups}. */ | ||||
| public class GroupList extends JsArray<GroupInfo> { | ||||
|   public static void my(AsyncCallback<GroupList> callback) { | ||||
|     new RestApi("accounts/self/groups").get(callback); | ||||
|     new RestApi("/accounts/self/groups").get(callback); | ||||
|   } | ||||
|  | ||||
|   public static void included(AccountGroup.UUID group, | ||||
|       AsyncCallback<GroupList> callback) { | ||||
|     new RestApi("groups").id(group.get()).view("groups").get(callback); | ||||
|     new RestApi("/groups/").id(group.get()).view("groups").get(callback); | ||||
|   } | ||||
|  | ||||
|   protected GroupList() { | ||||
|   | ||||
| @@ -52,7 +52,7 @@ public class GroupMap extends NativeMap<GroupInfo> { | ||||
|   } | ||||
|  | ||||
|   private static RestApi groups() { | ||||
|     return new RestApi("groups"); | ||||
|     return new RestApi("/groups/"); | ||||
|   } | ||||
|  | ||||
|   protected GroupMap() { | ||||
|   | ||||
| @@ -23,7 +23,7 @@ import com.google.gwt.user.client.rpc.AsyncCallback; | ||||
| public class MemberList extends JsArray<AccountInfo> { | ||||
|   public static void all(AccountGroup.UUID group, | ||||
|       AsyncCallback<MemberList> callback) { | ||||
|     new RestApi("groups").id(group.get()).view("members").get(callback); | ||||
|     new RestApi("/groups/").id(group.get()).view("members").get(callback); | ||||
|   } | ||||
|  | ||||
|   protected MemberList() { | ||||
|   | ||||
| @@ -100,7 +100,7 @@ class ReviewedPanels { | ||||
|         fileList.updateReviewedStatus(patchKey, reviewed); | ||||
|       } | ||||
|  | ||||
|       RestApi api = new RestApi("changes").id(ps.getParentKey().get()) | ||||
|       RestApi api = new RestApi("/changes/").id(ps.getParentKey().get()) | ||||
|           .view("revisions").id(ps.get()) | ||||
|           .view("files").id(patchKey.getFileName()) | ||||
|           .view("reviewed"); | ||||
|   | ||||
| @@ -21,7 +21,7 @@ import com.google.gwt.user.client.rpc.AsyncCallback; | ||||
| /** Plugins available from {@code /plugins/}. */ | ||||
| public class PluginMap extends NativeMap<PluginInfo> { | ||||
|   public static void all(AsyncCallback<PluginMap> callback) { | ||||
|     new RestApi("plugins") | ||||
|     new RestApi("/plugins/") | ||||
|       .addParameterTrue("all") | ||||
|       .get(NativeMap.copyKeysIntoChildren(callback)); | ||||
|   } | ||||
|   | ||||
| @@ -40,7 +40,7 @@ public class ProjectApi { | ||||
|     input.setParent(parent); | ||||
|     input.setPermissionsOnly(permissionsOnly); | ||||
|     input.setCreateEmptyCommit(createEmptyCcommit); | ||||
|     new RestApi("projects").id(projectName).ifNoneMatch() | ||||
|     new RestApi("/projects/").id(projectName).ifNoneMatch() | ||||
|         .put(input, cb); | ||||
|   } | ||||
|  | ||||
| @@ -194,7 +194,7 @@ public class ProjectApi { | ||||
|   } | ||||
|  | ||||
|   public static RestApi project(Project.NameKey name) { | ||||
|     return new RestApi("projects").id(name.get()); | ||||
|     return new RestApi("/projects/").id(name.get()); | ||||
|   } | ||||
|  | ||||
|   private static class ProjectInput extends JavaScriptObject { | ||||
|   | ||||
| @@ -21,7 +21,7 @@ import com.google.gwt.user.client.rpc.AsyncCallback; | ||||
| /** Projects available from {@code /projects/}. */ | ||||
| public class ProjectMap extends NativeMap<ProjectInfo> { | ||||
|   public static void all(AsyncCallback<ProjectMap> callback) { | ||||
|     projects() | ||||
|     new RestApi("/projects/") | ||||
|         .addParameterRaw("type", "ALL") | ||||
|         .addParameterTrue("all") | ||||
|         .addParameterTrue("d") // description | ||||
| @@ -29,7 +29,7 @@ public class ProjectMap extends NativeMap<ProjectInfo> { | ||||
|   } | ||||
|  | ||||
|   public static void permissions(AsyncCallback<ProjectMap> callback) { | ||||
|     projects() | ||||
|     new RestApi("/projects/") | ||||
|         .addParameterRaw("type", "PERMISSIONS") | ||||
|         .addParameterTrue("all") | ||||
|         .addParameterTrue("d") // description | ||||
| @@ -37,7 +37,7 @@ public class ProjectMap extends NativeMap<ProjectInfo> { | ||||
|   } | ||||
|  | ||||
|   public static void parentCandidates(AsyncCallback<ProjectMap> callback) { | ||||
|     projects() | ||||
|     new RestApi("/projects/") | ||||
|         .addParameterRaw("type", "PARENT_CANDIDATES") | ||||
|         .addParameterTrue("all") | ||||
|         .addParameterTrue("d") // description | ||||
| @@ -45,7 +45,7 @@ public class ProjectMap extends NativeMap<ProjectInfo> { | ||||
|   } | ||||
|  | ||||
|   public static void suggest(String prefix, int limit, AsyncCallback<ProjectMap> cb) { | ||||
|     projects() | ||||
|     new RestApi("/projects/") | ||||
|         .addParameter("p", prefix) | ||||
|         .addParameter("n", limit) | ||||
|         .addParameterRaw("type", "ALL") | ||||
| @@ -55,7 +55,7 @@ public class ProjectMap extends NativeMap<ProjectInfo> { | ||||
|   } | ||||
|  | ||||
|   public static void match(String match, int limit, int start, AsyncCallback<ProjectMap> cb) { | ||||
|     RestApi call = projects(); | ||||
|     RestApi call = new RestApi("/projects/"); | ||||
|     if (match != null) { | ||||
|       if (match.startsWith("^")) { | ||||
|         call.addParameter("r", match); | ||||
| @@ -78,10 +78,6 @@ public class ProjectMap extends NativeMap<ProjectInfo> { | ||||
|     match(match, 0, 0, cb); | ||||
|   } | ||||
|  | ||||
|   private static RestApi projects() { | ||||
|     return new RestApi("projects"); | ||||
|   } | ||||
|  | ||||
|   protected ProjectMap() { | ||||
|   } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Edwin Kempin
					Edwin Kempin