aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDuarte Meneses <duarte.meneses@sonarsource.com>2021-06-30 13:47:02 -0400
committersonartech <sonartech@sonarsource.com>2021-07-01 20:03:19 +0000
commitb5566d14514a36eec77e4fc21133167653e53965 (patch)
tree189bc22122d2427fc6f35e38f313ea4a735b5391
parentc1f985398916637be241e6f052bf5977e5fb28e3 (diff)
downloadsonarqube-b5566d14514a36eec77e4fc21133167653e53965.tar.gz
sonarqube-b5566d14514a36eec77e4fc21133167653e53965.zip
SONAR-15118 Reading DevOps response header should be case-insensitive
-rw-r--r--server/sonar-alm-client/src/main/java/org/sonar/alm/client/github/GithubApplicationHttpClientImpl.java2
-rw-r--r--server/sonar-alm-client/src/main/java/org/sonar/alm/client/gitlab/GitlabHttpClient.java8
-rw-r--r--server/sonar-alm-client/src/test/java/org/sonar/alm/client/github/GithubApplicationHttpClientImplTest.java11
-rw-r--r--server/sonar-alm-client/src/test/java/org/sonar/alm/client/gitlab/GitlabHttpClientTest.java37
-rw-r--r--server/sonar-auth-common/src/main/java/org/sonar/auth/OAuthRestClient.java10
-rw-r--r--server/sonar-auth-common/src/test/java/org/sonar/auth/OAuthRestClientTest.java14
6 files changed, 75 insertions, 7 deletions
diff --git a/server/sonar-alm-client/src/main/java/org/sonar/alm/client/github/GithubApplicationHttpClientImpl.java b/server/sonar-alm-client/src/main/java/org/sonar/alm/client/github/GithubApplicationHttpClientImpl.java
index 0f56ffc5c52..71b654655dd 100644
--- a/server/sonar-alm-client/src/main/java/org/sonar/alm/client/github/GithubApplicationHttpClientImpl.java
+++ b/server/sonar-alm-client/src/main/java/org/sonar/alm/client/github/GithubApplicationHttpClientImpl.java
@@ -203,7 +203,7 @@ public class GithubApplicationHttpClientImpl implements GithubApplicationHttpCli
@CheckForNull
private static String readNextEndPoint(okhttp3.Response response) {
- String links = response.header("link");
+ String links = response.headers().get("link");
if (links == null || links.isEmpty() || !links.contains("rel=\"next\"")) {
return null;
}
diff --git a/server/sonar-alm-client/src/main/java/org/sonar/alm/client/gitlab/GitlabHttpClient.java b/server/sonar-alm-client/src/main/java/org/sonar/alm/client/gitlab/GitlabHttpClient.java
index ffe6e647de6..4932e2db87e 100644
--- a/server/sonar-alm-client/src/main/java/org/sonar/alm/client/gitlab/GitlabHttpClient.java
+++ b/server/sonar-alm-client/src/main/java/org/sonar/alm/client/gitlab/GitlabHttpClient.java
@@ -29,6 +29,7 @@ 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;
@@ -302,11 +303,12 @@ 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"));
+ int totalProjects = parseAndGetIntegerHeader(headers.get("X-Total"));
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.");
diff --git a/server/sonar-alm-client/src/test/java/org/sonar/alm/client/github/GithubApplicationHttpClientImplTest.java b/server/sonar-alm-client/src/test/java/org/sonar/alm/client/github/GithubApplicationHttpClientImplTest.java
index 5922ececdb2..8bbf5da3a70 100644
--- a/server/sonar-alm-client/src/test/java/org/sonar/alm/client/github/GithubApplicationHttpClientImplTest.java
+++ b/server/sonar-alm-client/src/test/java/org/sonar/alm/client/github/GithubApplicationHttpClientImplTest.java
@@ -162,6 +162,17 @@ public class GithubApplicationHttpClientImplTest {
assertThat(response.getNextEndPoint()).contains("https://api.github.com/installation/repositories?per_page=5&page=2");
}
+ @Test
+ public void get_returns_endPoint_when_link_header_has_next_rel_different_case() throws IOException {
+ String linkHeader = "<https://api.github.com/installation/repositories?per_page=5&page=2>; rel=\"next\"";
+ server.enqueue(new MockResponse().setBody(randomBody)
+ .setHeader("Link", linkHeader));
+
+ GetResponse response = underTest.get(appUrl, accessToken, randomEndPoint);
+
+ assertThat(response.getNextEndPoint()).contains("https://api.github.com/installation/repositories?per_page=5&page=2");
+ }
+
@DataProvider
public static Object[][] linkHeadersWithNextRel() {
String expected = "https://api.github.com/installation/repositories?per_page=5&page=2";
diff --git a/server/sonar-alm-client/src/test/java/org/sonar/alm/client/gitlab/GitlabHttpClientTest.java b/server/sonar-alm-client/src/test/java/org/sonar/alm/client/gitlab/GitlabHttpClientTest.java
index 283371f2cb4..229f26f6ebe 100644
--- a/server/sonar-alm-client/src/test/java/org/sonar/alm/client/gitlab/GitlabHttpClientTest.java
+++ b/server/sonar-alm-client/src/test/java/org/sonar/alm/client/gitlab/GitlabHttpClientTest.java
@@ -244,6 +244,43 @@ public class GitlabHttpClientTest {
}
@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()
.setResponseCode(200)
diff --git a/server/sonar-auth-common/src/main/java/org/sonar/auth/OAuthRestClient.java b/server/sonar-auth-common/src/main/java/org/sonar/auth/OAuthRestClient.java
index 8a95fba3c95..c21795d5aef 100644
--- a/server/sonar-auth-common/src/main/java/org/sonar/auth/OAuthRestClient.java
+++ b/server/sonar-auth-common/src/main/java/org/sonar/auth/OAuthRestClient.java
@@ -27,6 +27,7 @@ import com.github.scribejava.core.oauth.OAuth20Service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.function.Function;
@@ -81,11 +82,14 @@ public class OAuthRestClient {
}
private static Optional<String> readNextEndPoint(Response response) {
- String link = response.getHeader("Link");
- if (link == null || link.isEmpty() || !link.contains("rel=\"next\"")) {
+ Optional<String> link = response.getHeaders().entrySet().stream()
+ .filter(e -> "Link".equalsIgnoreCase(e.getKey()))
+ .map(Map.Entry::getValue)
+ .findAny();
+ if (link.isEmpty() || link.get().isEmpty() || !link.get().contains("rel=\"next\"")) {
return Optional.empty();
}
- Matcher nextLinkMatcher = NEXT_LINK_PATTERN.matcher(link);
+ Matcher nextLinkMatcher = NEXT_LINK_PATTERN.matcher(link.get());
if (!nextLinkMatcher.find()) {
return Optional.empty();
}
diff --git a/server/sonar-auth-common/src/test/java/org/sonar/auth/OAuthRestClientTest.java b/server/sonar-auth-common/src/test/java/org/sonar/auth/OAuthRestClientTest.java
index 60be82738b0..3f29fd2597d 100644
--- a/server/sonar-auth-common/src/test/java/org/sonar/auth/OAuthRestClientTest.java
+++ b/server/sonar-auth-common/src/test/java/org/sonar/auth/OAuthRestClientTest.java
@@ -98,6 +98,20 @@ public class OAuthRestClientTest {
}
@Test
+ public void execute_paginated_request_case_insensitive_headers() {
+ mockWebServer.enqueue(new MockResponse()
+ .setHeader("link", "<" + serverUrl + "/test?per_page=100&page=2>; rel=\"next\", <" + serverUrl + "/test?per_page=100&page=2>; rel=\"last\"")
+ .setBody("A"));
+ mockWebServer.enqueue(new MockResponse()
+ .setHeader("link", "<" + serverUrl + "/test?per_page=100&page=1>; rel=\"prev\", <" + serverUrl + "/test?per_page=100&page=1>; rel=\"first\"")
+ .setBody("B"));
+
+ List<String> response = executePaginatedRequest(serverUrl + "/test", oAuth20Service, auth2AccessToken, Arrays::asList);
+
+ assertThat(response).contains("A", "B");
+ }
+
+ @Test
public void fail_to_executed_paginated_request() {
mockWebServer.enqueue(new MockResponse()
.setHeader("Link", "<" + serverUrl + "/test?per_page=100&page=2>; rel=\"next\", <" + serverUrl + "/test?per_page=100&page=2>; rel=\"last\"")