aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-webserver-ws
diff options
context:
space:
mode:
authorJacek <jacek.poreda@sonarsource.com>2021-05-27 15:32:09 +0200
committersonartech <sonartech@sonarsource.com>2021-06-10 20:03:26 +0000
commita9ff34a88b68a2f1df68bc1fe54ebf5b17f4e70a (patch)
tree0dd00436a41c2debadcb7b9520c745ab69bfde73 /server/sonar-webserver-ws
parent798f3746ed177297ef2e4399e0350cfbb8679d15 (diff)
downloadsonarqube-a9ff34a88b68a2f1df68bc1fe54ebf5b17f4e70a.tar.gz
sonarqube-a9ff34a88b68a2f1df68bc1fe54ebf5b17f4e70a.zip
SONAR-14871 Basic project binding validation endpoint
- Add 'scope' field to HTTP error messages
Diffstat (limited to 'server/sonar-webserver-ws')
-rw-r--r--server/sonar-webserver-ws/src/main/java/org/sonar/server/ws/WebServiceEngine.java18
-rw-r--r--server/sonar-webserver-ws/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java20
2 files changed, 32 insertions, 6 deletions
diff --git a/server/sonar-webserver-ws/src/main/java/org/sonar/server/ws/WebServiceEngine.java b/server/sonar-webserver-ws/src/main/java/org/sonar/server/ws/WebServiceEngine.java
index 715607cee1e..52082613569 100644
--- a/server/sonar-webserver-ws/src/main/java/org/sonar/server/ws/WebServiceEngine.java
+++ b/server/sonar-webserver-ws/src/main/java/org/sonar/server/ws/WebServiceEngine.java
@@ -28,16 +28,17 @@ import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.apache.catalina.connector.ClientAbortException;
import org.picocontainer.Startable;
+import org.sonar.api.impl.ws.ValidatingRequest;
import org.sonar.api.server.ServerSide;
import org.sonar.api.server.ws.LocalConnector;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
-import org.sonar.api.impl.ws.ValidatingRequest;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.exceptions.BadConfigurationException;
import org.sonar.server.exceptions.ServerException;
import org.sonarqube.ws.MediaTypes;
@@ -48,9 +49,9 @@ import static java.util.Objects.requireNonNull;
import static org.apache.commons.lang.StringUtils.substring;
import static org.apache.commons.lang.StringUtils.substringAfterLast;
import static org.apache.commons.lang.StringUtils.substringBeforeLast;
+import static org.sonar.server.exceptions.NotFoundException.checkFound;
import static org.sonar.server.ws.RequestVerifier.verifyRequest;
import static org.sonar.server.ws.ServletRequest.SUPPORTED_MEDIA_TYPES_BY_URL_SUFFIX;
-import static org.sonar.server.exceptions.NotFoundException.checkFound;
/**
* @since 4.2
@@ -110,6 +111,8 @@ public class WebServiceEngine implements LocalConnector, Startable {
action.handler().handle(request, response);
} catch (IllegalArgumentException e) {
sendErrors(request, response, e, 400, singletonList(e.getMessage()));
+ } catch (BadConfigurationException e) {
+ sendErrors(request, response, e, 400, e.errors(), e.scope());
} catch (BadRequestException e) {
sendErrors(request, response, e, 400, e.errors());
} catch (ServerException e) {
@@ -128,6 +131,10 @@ public class WebServiceEngine implements LocalConnector, Startable {
}
private static void sendErrors(Request request, Response response, Exception exception, int status, List<String> errors) {
+ sendErrors(request, response, exception, status, errors, null);
+ }
+
+ private static void sendErrors(Request request, Response response, Exception exception, int status, List<String> errors, @Nullable String scope) {
if (isRequestAbortedByClient(exception)) {
// do not pollute logs. We can't do anything -> use DEBUG level
// see org.sonar.server.ws.ServletResponse#output()
@@ -160,6 +167,7 @@ public class WebServiceEngine implements LocalConnector, Startable {
stream.setMediaType(MediaTypes.JSON);
try (JsonWriter json = JsonWriter.of(new OutputStreamWriter(stream.output(), StandardCharsets.UTF_8))) {
json.beginObject();
+ writeScope(scope, json);
writeErrors(json, errors);
json.endObject();
} catch (Exception e) {
@@ -168,6 +176,12 @@ public class WebServiceEngine implements LocalConnector, Startable {
}
}
+ private static void writeScope(@Nullable String scope, JsonWriter json) {
+ if (scope != null) {
+ json.prop("scope", scope);
+ }
+ }
+
private static boolean isRequestAbortedByClient(Exception exception) {
return Throwables.getCausalChain(exception).stream().anyMatch(t -> t instanceof ClientAbortException);
}
diff --git a/server/sonar-webserver-ws/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java b/server/sonar-webserver-ws/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java
index 7b86c69e5e7..47d301ff577 100644
--- a/server/sonar-webserver-ws/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java
+++ b/server/sonar-webserver-ws/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java
@@ -24,7 +24,6 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.connector.ClientAbortException;
import org.junit.Rule;
import org.junit.Test;
-import org.junit.rules.ExpectedException;
import org.mockito.Mockito;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.RequestHandler;
@@ -32,6 +31,7 @@ import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.log.LogTester;
import org.sonar.api.utils.log.LoggerLevel;
+import org.sonar.server.exceptions.BadConfigurationException;
import org.sonar.server.exceptions.BadRequestException;
import org.sonarqube.ws.MediaTypes;
@@ -50,9 +50,6 @@ public class WebServiceEngineTest {
@Rule
public LogTester logTester = new LogTester();
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
@Test
public void load_ws_definitions_at_startup() {
WebServiceEngine underTest = new WebServiceEngine(new WebService[] {
@@ -337,6 +334,21 @@ public class WebServiceEngineTest {
}
@Test
+ public void return_400_on_BadConfigurationException_with_single_message_and_scope() {
+ Request request = new TestRequest().setPath("api/foo");
+
+ DumbResponse response = run(request, newWs("api/foo", a -> a.setHandler((req, resp) -> {
+ throw new BadConfigurationException("PROJECT", "Bad request !");
+ })));
+
+ assertThat(response.stream().outputAsString()).isEqualTo(
+ "{\"scope\":\"PROJECT\",\"errors\":[{\"msg\":\"Bad request !\"}]}");
+ assertThat(response.stream().status()).isEqualTo(400);
+ assertThat(response.stream().mediaType()).isEqualTo(MediaTypes.JSON);
+ assertThat(logTester.logs(LoggerLevel.ERROR)).isEmpty();
+ }
+
+ @Test
public void return_error_message_containing_character_percent() {
Request request = new TestRequest().setPath("api/foo");