]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-15488 x-total header is optional
authorPierre <pierre.guillot@sonarsource.com>
Fri, 8 Oct 2021 09:15:06 +0000 (11:15 +0200)
committersonartech <sonartech@sonarsource.com>
Tue, 19 Oct 2021 20:03:29 +0000 (20:03 +0000)
server/sonar-alm-client/src/main/java/org/sonar/alm/client/gitlab/GitlabHttpClient.java
server/sonar-alm-client/src/main/java/org/sonar/alm/client/gitlab/ProjectList.java
server/sonar-alm-client/src/test/java/org/sonar/alm/client/gitlab/GitlabHttpClientTest.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/almintegration/ws/gitlab/SearchGitlabReposAction.java

index c763bf98df02ffb0e92603d373820dca213090e9..2dc3d3a617343a5ba3ec760c8787d458419b43fa 100644 (file)
@@ -29,10 +29,12 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
 import javax.annotation.Nullable;
+import okhttp3.Headers;
 import okhttp3.OkHttpClient;
 import okhttp3.Request;
 import okhttp3.RequestBody;
 import okhttp3.Response;
+import org.apache.logging.log4j.util.Strings;
 import org.sonar.alm.client.TimeoutConfiguration;
 import org.sonar.api.server.ServerSide;
 import org.sonar.api.utils.log.Logger;
@@ -273,11 +275,13 @@ public class GitlabHttpClient {
       .build();
 
     try (Response response = client.newCall(request).execute()) {
+      Headers headers = response.headers();
       checkResponseIsSuccessful(response, "Could not get projects from GitLab instance");
       List<Project> projectList = Project.parseJsonArray(response.body().string());
-      int returnedPageNumber = parseAndGetIntegerHeader(response.header("X-Page"));
-      int returnedPageSize = parseAndGetIntegerHeader(response.header("X-Per-Page"));
-      int totalProjects = parseAndGetIntegerHeader(response.header("X-Total"));
+      int returnedPageNumber = parseAndGetIntegerHeader(headers.get("X-Page"));
+      int returnedPageSize = parseAndGetIntegerHeader(headers.get("X-Per-Page"));
+      String xtotal = headers.get("X-Total");
+      Integer totalProjects = Strings.isEmpty(xtotal) ? null : parseAndGetIntegerHeader(xtotal);
       return new ProjectList(projectList, returnedPageNumber, returnedPageSize, totalProjects);
     } catch (JsonSyntaxException e) {
       throw new IllegalArgumentException("Could not parse GitLab answer to search projects. Got a non-json payload as result.");
index 6548e6699229baed8b1797ca271b899c506729c8..9450b67d2203ab0f23104455d7d80e6ca3ecb845 100644 (file)
 package org.sonar.alm.client.gitlab;
 
 import java.util.List;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
 
 public class ProjectList {
 
   private final List<Project> projects;
   private final int pageNumber;
   private final int pageSize;
-  private final int total;
+  private final Integer total;
 
-  public ProjectList(List<Project> projects, int pageNumber, int pageSize, int total) {
+  public ProjectList(List<Project> projects, int pageNumber, int pageSize, @Nullable Integer total) {
     this.projects = projects;
     this.pageNumber = pageNumber;
     this.pageSize = pageSize;
@@ -47,7 +49,8 @@ public class ProjectList {
     return pageSize;
   }
 
-  public int getTotal() {
+  @CheckForNull
+  public Integer getTotal() {
     return total;
   }
 }
index 228d21a2349051231ebaae50e77cde834e0f6ecf..84ffc190206113f6e091e0aff04a1425ea1a8f66 100644 (file)
@@ -242,6 +242,79 @@ public class GitlabHttpClientTest {
     assertThat(projectGitlabRequest.getMethod()).isEqualTo("GET");
   }
 
+  @Test
+  public void search_projects_dont_fail_if_no_x_total() throws InterruptedException {
+    MockResponse projects = new MockResponse()
+      .setResponseCode(200)
+      .setBody("[\n"
+        + "  {\n"
+        + "    \"id\": 1,\n"
+        + "    \"name\": \"SonarQube example 1\",\n"
+        + "    \"name_with_namespace\": \"SonarSource / SonarQube / SonarQube example 1\",\n"
+        + "    \"path\": \"sonarqube-example-1\",\n"
+        + "    \"path_with_namespace\": \"sonarsource/sonarqube/sonarqube-example-1\",\n"
+        + "    \"web_url\": \"https://example.gitlab.com/sonarsource/sonarqube/sonarqube-example-1\"\n"
+        + "  }"
+        + "]");
+    projects.addHeader("X-Page", 1);
+    projects.addHeader("X-Per-Page", 10);
+    server.enqueue(projects);
+
+    ProjectList projectList = underTest.searchProjects(gitlabUrl, "pat", "example", 1, 10);
+
+    assertThat(projectList.getPageNumber()).isEqualTo(1);
+    assertThat(projectList.getPageSize()).isEqualTo(10);
+    assertThat(projectList.getTotal()).isNull();
+
+    assertThat(projectList.getProjects()).hasSize(1);
+    assertThat(projectList.getProjects()).extracting(
+      Project::getId, Project::getName, Project::getNameWithNamespace, Project::getPath, Project::getPathWithNamespace, Project::getWebUrl).containsExactly(
+      tuple(1L, "SonarQube example 1", "SonarSource / SonarQube / SonarQube example 1", "sonarqube-example-1", "sonarsource/sonarqube/sonarqube-example-1",
+        "https://example.gitlab.com/sonarsource/sonarqube/sonarqube-example-1"));
+
+    RecordedRequest projectGitlabRequest = server.takeRequest(10, TimeUnit.SECONDS);
+    String gitlabUrlCall = projectGitlabRequest.getRequestUrl().toString();
+    assertThat(gitlabUrlCall).isEqualTo(server.url("") + "projects?archived=false&simple=true&membership=true&order_by=name&sort=asc&search=example&page=1&per_page=10");
+    assertThat(projectGitlabRequest.getMethod()).isEqualTo("GET");
+  }
+
+  @Test
+  public void search_projects_with_case_insensitive_pagination_headers() throws InterruptedException {
+    MockResponse projects1 = new MockResponse()
+      .setResponseCode(200)
+      .setBody("[\n"
+        + "  {\n"
+        + "    \"id\": 1,\n"
+        + "    \"name\": \"SonarQube example 1\",\n"
+        + "    \"name_with_namespace\": \"SonarSource / SonarQube / SonarQube example 1\",\n"
+        + "    \"path\": \"sonarqube-example-1\",\n"
+        + "    \"path_with_namespace\": \"sonarsource/sonarqube/sonarqube-example-1\",\n"
+        + "    \"web_url\": \"https://example.gitlab.com/sonarsource/sonarqube/sonarqube-example-1\"\n"
+        + "  }"
+        + "]");
+    projects1.addHeader("x-page", 1);
+    projects1.addHeader("x-Per-page", 1);
+    projects1.addHeader("X-Total", 2);
+    server.enqueue(projects1);
+
+    ProjectList projectList = underTest.searchProjects(gitlabUrl, "pat", "example", 1, 10);
+
+    assertThat(projectList.getPageNumber()).isEqualTo(1);
+    assertThat(projectList.getPageSize()).isEqualTo(1);
+    assertThat(projectList.getTotal()).isEqualTo(2);
+
+    assertThat(projectList.getProjects()).hasSize(1);
+    assertThat(projectList.getProjects()).extracting(
+      Project::getId, Project::getName, Project::getNameWithNamespace, Project::getPath, Project::getPathWithNamespace, Project::getWebUrl).containsExactly(
+      tuple(1L, "SonarQube example 1", "SonarSource / SonarQube / SonarQube example 1", "sonarqube-example-1", "sonarsource/sonarqube/sonarqube-example-1",
+        "https://example.gitlab.com/sonarsource/sonarqube/sonarqube-example-1"));
+
+    RecordedRequest projectGitlabRequest = server.takeRequest(10, TimeUnit.SECONDS);
+    String gitlabUrlCall = projectGitlabRequest.getRequestUrl().toString();
+    assertThat(gitlabUrlCall).isEqualTo(server.url("") + "projects?archived=false&simple=true&membership=true&order_by=name&sort=asc&search=example&page=1&per_page=10");
+    assertThat(projectGitlabRequest.getMethod()).isEqualTo("GET");
+  }
+
   @Test
   public void search_projects_projectName_param_should_be_encoded() throws InterruptedException {
     MockResponse projects = new MockResponse()
index b3214bbd4588eed2af5ac8a7da2e8d3cbda8cb19..56c86113a7610d4457b7ed6b442a2f60503caa15 100644 (file)
@@ -123,13 +123,16 @@ public class SearchGitlabReposAction implements AlmIntegrationsWsAction {
         .map(project -> toGitlabRepository(project, sqProjectsKeyByGitlabProjectId))
         .collect(toList());
 
+      Paging.Builder pagingBuilder = Paging.newBuilder()
+        .setPageIndex(gitlabProjectList.getPageNumber())
+        .setPageSize(gitlabProjectList.getPageSize());
+      Integer gitlabProjectListTotal = gitlabProjectList.getTotal();
+      if (gitlabProjectListTotal != null) {
+        pagingBuilder.setTotal(gitlabProjectListTotal);
+      }
       return AlmIntegrations.SearchGitlabReposWsResponse.newBuilder()
         .addAllRepositories(gitlabRepositories)
-        .setPaging(Paging.newBuilder()
-          .setPageIndex(gitlabProjectList.getPageNumber())
-          .setPageSize(gitlabProjectList.getPageSize())
-          .setTotal(gitlabProjectList.getTotal())
-          .build())
+        .setPaging(pagingBuilder.build())
         .build();
     }
   }