diff options
author | Jacek <jacek.poreda@sonarsource.com> | 2021-05-27 15:32:09 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2021-06-10 20:03:26 +0000 |
commit | a9ff34a88b68a2f1df68bc1fe54ebf5b17f4e70a (patch) | |
tree | 0dd00436a41c2debadcb7b9520c745ab69bfde73 /server/sonar-webserver-ws/src | |
parent | 798f3746ed177297ef2e4399e0350cfbb8679d15 (diff) | |
download | sonarqube-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/src')
-rw-r--r-- | server/sonar-webserver-ws/src/main/java/org/sonar/server/ws/WebServiceEngine.java | 18 | ||||
-rw-r--r-- | server/sonar-webserver-ws/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java | 20 |
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"); |