aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-ws
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@sonarsource.com>2017-08-23 17:18:08 +0200
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>2017-09-13 15:50:49 +0200
commit9d5fc95ed97f0dc0e1a797065b5a3870449a9ded (patch)
tree91126ec5e0985e48887a078ecf757737bca88616 /sonar-ws
parent5b9d6018431f09d090b71fa3179a9d9bed5dc0ab (diff)
downloadsonarqube-9d5fc95ed97f0dc0e1a797065b5a3870449a9ded.tar.gz
sonarqube-9d5fc95ed97f0dc0e1a797065b5a3870449a9ded.zip
SONAR-9740 support HTTP headers in API Request and sonar-ws
Diffstat (limited to 'sonar-ws')
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/BaseRequest.java40
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/Headers.java36
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/HttpConnector.java7
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/LocalWsConnector.java14
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/WsRequest.java2
-rw-r--r--sonar-ws/src/test/java/org/sonarqube/ws/client/BaseRequestTest.java18
-rw-r--r--sonar-ws/src/test/java/org/sonarqube/ws/client/HttpConnectorTest.java31
7 files changed, 140 insertions, 8 deletions
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/BaseRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/BaseRequest.java
index db88b99821a..8b5fbcff005 100644
--- a/sonar-ws/src/main/java/org/sonarqube/ws/client/BaseRequest.java
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/BaseRequest.java
@@ -22,10 +22,12 @@ package org.sonarqube.ws.client;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.ListMultimap;
import java.util.Collection;
+import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -36,6 +38,7 @@ import org.sonarqube.ws.MediaTypes;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.util.Collections.singletonList;
+import static java.util.Collections.unmodifiableSet;
import static java.util.Objects.requireNonNull;
abstract class BaseRequest<SELF extends BaseRequest> implements WsRequest {
@@ -45,6 +48,7 @@ abstract class BaseRequest<SELF extends BaseRequest> implements WsRequest {
private String mediaType = MediaTypes.JSON;
private final DefaultParameters parameters = new DefaultParameters();
+ private final DefaultHeaders headers = new DefaultHeaders();
BaseRequest(String path) {
this.path = path;
@@ -131,6 +135,17 @@ abstract class BaseRequest<SELF extends BaseRequest> implements WsRequest {
return parameters;
}
+ @Override
+ public Headers getHeaders() {
+ return headers;
+ }
+
+ public SELF setHeader(String name, @Nullable String value) {
+ requireNonNull(name, "Header name can't be null");
+ headers.setValue(name, value);
+ return (SELF) this;
+ }
+
private static class DefaultParameters implements Parameters {
// preserve insertion order
private final ListMultimap<String, String> keyValues = LinkedListMultimap.create();
@@ -168,4 +183,29 @@ abstract class BaseRequest<SELF extends BaseRequest> implements WsRequest {
return this;
}
}
+
+ private static class DefaultHeaders implements Headers {
+ private final Map<String, String> keyValues = new HashMap<>();
+
+ @Override
+ public Optional<String> getValue(String name) {
+ return Optional.ofNullable(keyValues.get(name));
+ }
+
+ private DefaultHeaders setValue(String name, @Nullable String value) {
+ checkArgument(!isNullOrEmpty(name));
+
+ if (value == null) {
+ keyValues.remove(name);
+ } else {
+ keyValues.put(name, value);
+ }
+ return this;
+ }
+
+ @Override
+ public Set<String> getNames() {
+ return unmodifiableSet(keyValues.keySet());
+ }
+ }
}
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/Headers.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/Headers.java
new file mode 100644
index 00000000000..b289789a1f2
--- /dev/null
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/Headers.java
@@ -0,0 +1,36 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonarqube.ws.client;
+
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * HTTP headers
+ *
+ * @since 6.6
+ */
+public interface Headers {
+
+ Optional<String> getValue(String name);
+
+ Set<String> getNames();
+
+}
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/HttpConnector.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/HttpConnector.java
index e652a21e28f..fcc970b7b05 100644
--- a/sonar-ws/src/main/java/org/sonarqube/ws/client/HttpConnector.java
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/HttpConnector.java
@@ -159,11 +159,13 @@ public class HttpConnector implements WsConnector {
private Request.Builder prepareOkRequestBuilder(WsRequest getRequest, HttpUrl.Builder urlBuilder) {
Request.Builder okHttpRequestBuilder = new Request.Builder()
.url(urlBuilder.build())
- .addHeader("Accept", getRequest.getMediaType())
- .addHeader("Accept-Charset", "UTF-8");
+ .header("Accept", getRequest.getMediaType())
+ .header("Accept-Charset", "UTF-8");
if (credentials != null) {
okHttpRequestBuilder.header("Authorization", credentials);
}
+ getRequest.getHeaders().getNames().forEach(name ->
+ okHttpRequestBuilder.header(name, getRequest.getHeaders().getValue(name).get()));
return okHttpRequestBuilder;
}
@@ -199,6 +201,7 @@ public class HttpConnector implements WsConnector {
/**
* Private since 5.5.
+ *
* @see HttpConnector#newBuilder()
*/
private Builder() {
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/LocalWsConnector.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/LocalWsConnector.java
index 3f2cee3a5c7..5dca504438e 100644
--- a/sonar-ws/src/main/java/org/sonarqube/ws/client/LocalWsConnector.java
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/LocalWsConnector.java
@@ -25,6 +25,7 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.List;
+import java.util.Optional;
import org.sonar.api.server.ws.LocalConnector;
import static java.nio.charset.StandardCharsets.UTF_8;
@@ -56,11 +57,9 @@ class LocalWsConnector implements WsConnector {
private static class DefaultLocalRequest implements LocalConnector.LocalRequest {
private final WsRequest wsRequest;
- private final Parameters parameters;
public DefaultLocalRequest(WsRequest wsRequest) {
this.wsRequest = wsRequest;
- this.parameters = wsRequest.getParameters();
}
@Override
@@ -80,17 +79,22 @@ class LocalWsConnector implements WsConnector {
@Override
public boolean hasParam(String key) {
- return !parameters.getValues(key).isEmpty();
+ return !wsRequest.getParameters().getValues(key).isEmpty();
}
@Override
public String getParam(String key) {
- return parameters.getValue(key);
+ return wsRequest.getParameters().getValue(key);
}
@Override
public List<String> getMultiParam(String key) {
- return parameters.getValues(key);
+ return wsRequest.getParameters().getValues(key);
+ }
+
+ @Override
+ public Optional<String> getHeader(String name) {
+ return wsRequest.getHeaders().getValue(name);
}
}
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/WsRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/WsRequest.java
index b5ad96a4542..9907ae7b39e 100644
--- a/sonar-ws/src/main/java/org/sonarqube/ws/client/WsRequest.java
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/WsRequest.java
@@ -43,6 +43,8 @@ public interface WsRequest {
Parameters getParameters();
+ Headers getHeaders();
+
enum Method {
GET, POST
}
diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/BaseRequestTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/BaseRequestTest.java
index b473e805eef..c639641a079 100644
--- a/sonar-ws/src/test/java/org/sonarqube/ws/client/BaseRequestTest.java
+++ b/sonar-ws/src/test/java/org/sonarqube/ws/client/BaseRequestTest.java
@@ -38,7 +38,7 @@ public class BaseRequestTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
- FakeRequest underTest = new FakeRequest("api/foo");
+ private FakeRequest underTest = new FakeRequest("api/foo");
@Test
public void test_defaults() {
@@ -96,6 +96,22 @@ public class BaseRequestTest {
underTest.setParam(null, "val");
}
+ @Test
+ public void headers_are_empty_by_default() {
+ assertThat(underTest.getHeaders().getNames()).isEmpty();
+ }
+
+ @Test
+ public void set_and_get_headers() {
+ underTest.setHeader("foo", "fooz");
+ underTest.setHeader("bar", "barz");
+
+ assertThat(underTest.getHeaders().getNames()).containsExactlyInAnyOrder("foo", "bar");
+ assertThat(underTest.getHeaders().getValue("foo")).hasValue("fooz");
+ assertThat(underTest.getHeaders().getValue("bar")).hasValue("barz");
+ assertThat(underTest.getHeaders().getValue("xxx")).isEmpty();
+ }
+
private void assertParameters(MapEntry<String, String>... values) {
Parameters parameters = underTest.getParameters();
assertThat(parameters.getKeys()).extracting(key -> MapEntry.entry(key, parameters.getValue(key))).containsExactly(values);
diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/HttpConnectorTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/HttpConnectorTest.java
index 449b4fcebe8..c727235a939 100644
--- a/sonar-ws/src/test/java/org/sonarqube/ws/client/HttpConnectorTest.java
+++ b/sonar-ws/src/test/java/org/sonarqube/ws/client/HttpConnectorTest.java
@@ -96,6 +96,21 @@ public class HttpConnectorTest {
}
@Test
+ public void add_headers_to_GET_request() throws Exception {
+ answerHelloWorld();
+ GetRequest request = new GetRequest("api/issues/search")
+ .setHeader("X-Foo", "fooz")
+ .setHeader("X-Bar", "barz");
+
+ underTest = HttpConnector.newBuilder().url(serverUrl).build();
+ underTest.call(request);
+
+ RecordedRequest recordedRequest = server.takeRequest();
+ assertThat(recordedRequest.getHeader("X-Foo")).isEqualTo("fooz");
+ assertThat(recordedRequest.getHeader("X-Bar")).isEqualTo("barz");
+ }
+
+ @Test
public void use_basic_authentication() throws Exception {
answerHelloWorld();
underTest = HttpConnector.newBuilder()
@@ -256,6 +271,22 @@ public class HttpConnectorTest {
assertThat(recordedRequest.getMethod()).isEqualTo("POST");
assertThat(recordedRequest.getPath()).isEqualTo("/api/issues/search");
assertThat(recordedRequest.getBody().readUtf8()).isEqualTo("severity=MAJOR");
+ assertThat(recordedRequest.getHeader("Accept")).isEqualTo("application/x-protobuf");
+ }
+
+ @Test
+ public void add_header_to_POST_request() throws Exception {
+ answerHelloWorld();
+ PostRequest request = new PostRequest("api/issues/search")
+ .setHeader("X-Foo", "fooz")
+ .setHeader("X-Bar", "barz");
+
+ underTest = HttpConnector.newBuilder().url(serverUrl).build();
+ underTest.call(request);
+
+ RecordedRequest recordedRequest = server.takeRequest();
+ assertThat(recordedRequest.getHeader("X-Foo")).isEqualTo("fooz");
+ assertThat(recordedRequest.getHeader("X-Bar")).isEqualTo("barz");
}
@Test