Add a way to signal that an endpoint request is invalid
This commit adds InvalidEndpointRequestException as a technology agnostic way to signal that an endpoint request is invalid. When such exception is thrown, the web layer translates that to a 400. Rather than overriding the reason, this commit makes sure to reuse the error infrastructure. Closes gh-10618
This commit is contained in:
@@ -42,6 +42,7 @@ import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
@@ -157,8 +158,13 @@ public abstract class AbstractWebEndpointIntegrationTests<T extends Configurable
|
||||
|
||||
@Test
|
||||
public void readOperationWithMappingFailureProducesBadRequestResponse() {
|
||||
load(QueryEndpointConfiguration.class, (client) -> client.get()
|
||||
.uri("/query?two=two").exchange().expectStatus().isBadRequest());
|
||||
load(QueryEndpointConfiguration.class, (client) -> {
|
||||
WebTestClient.BodyContentSpec body = client.get()
|
||||
.uri("/query?two=two").exchange().expectStatus().isBadRequest()
|
||||
.expectBody();
|
||||
validateErrorBody(body, HttpStatus.BAD_REQUEST, "/endpoints/query",
|
||||
"Missing parameters: one");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -275,8 +281,13 @@ public abstract class AbstractWebEndpointIntegrationTests<T extends Configurable
|
||||
|
||||
@Test
|
||||
public void readOperationWithMissingRequiredParametersReturnsBadRequestResponse() {
|
||||
load(RequiredParameterEndpointConfiguration.class, (client) -> client.get()
|
||||
.uri("/requiredparameters").exchange().expectStatus().isBadRequest());
|
||||
load(RequiredParameterEndpointConfiguration.class, (client) -> {
|
||||
WebTestClient.BodyContentSpec body = client.get()
|
||||
.uri("/requiredparameters").exchange().expectStatus().isBadRequest()
|
||||
.expectBody();
|
||||
validateErrorBody(body, HttpStatus.BAD_REQUEST,
|
||||
"/endpoints/requiredparameters", "Missing parameters: foo");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -321,6 +332,14 @@ public abstract class AbstractWebEndpointIntegrationTests<T extends Configurable
|
||||
|
||||
protected abstract int getPort(T context);
|
||||
|
||||
protected void validateErrorBody(WebTestClient.BodyContentSpec body,
|
||||
HttpStatus status, String path, String message) {
|
||||
body.jsonPath("status").isEqualTo(status.value())
|
||||
.jsonPath("error").isEqualTo(status.getReasonPhrase())
|
||||
.jsonPath("path").isEqualTo(path)
|
||||
.jsonPath("message").isEqualTo(message);
|
||||
}
|
||||
|
||||
private void load(Class<?> configuration,
|
||||
BiConsumer<ApplicationContext, WebTestClient> consumer) {
|
||||
load(configuration, "/endpoints", consumer);
|
||||
|
||||
@@ -37,6 +37,8 @@ import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebSe
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
|
||||
/**
|
||||
* Integration tests for web endpoints exposed using Jersey.
|
||||
@@ -64,6 +66,12 @@ public class JerseyWebEndpointIntegrationTests extends
|
||||
return context.getWebServer().getPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateErrorBody(WebTestClient.BodyContentSpec body,
|
||||
HttpStatus status, String path, String message) {
|
||||
// Jersey doesn't support the general error page handling
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class JerseyConfiguration {
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ import org.junit.Test;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.AbstractWebEndpointIntegrationTests;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer;
|
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration;
|
||||
import org.springframework.boot.endpoint.web.EndpointMapping;
|
||||
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
|
||||
import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext;
|
||||
@@ -95,6 +97,7 @@ public class WebFluxEndpointIntegrationTests
|
||||
|
||||
@Configuration
|
||||
@EnableWebFlux
|
||||
@ImportAutoConfiguration(ErrorWebFluxAutoConfiguration.class)
|
||||
static class ReactiveConfiguration {
|
||||
|
||||
private int port;
|
||||
|
||||
@@ -23,6 +23,13 @@ import org.junit.Test;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.AbstractWebEndpointIntegrationTests;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer;
|
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration;
|
||||
import org.springframework.boot.endpoint.web.EndpointMapping;
|
||||
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
|
||||
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
|
||||
@@ -32,8 +39,6 @@ import org.springframework.core.env.Environment;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -89,7 +94,10 @@ public class MvcWebEndpointIntegrationTests extends
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
@ImportAutoConfiguration({ JacksonAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class,
|
||||
ServletWebServerFactoryAutoConfiguration.class, WebMvcAutoConfiguration.class,
|
||||
DispatcherServletAutoConfiguration.class, ErrorMvcAutoConfiguration.class })
|
||||
static class WebMvcConfiguration {
|
||||
|
||||
@Bean
|
||||
@@ -97,11 +105,6 @@ public class MvcWebEndpointIntegrationTests extends
|
||||
return new TomcatServletWebServerFactory(0);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DispatcherServlet dispatcherServlet() {
|
||||
return new DispatcherServlet();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WebMvcEndpointHandlerMapping webEndpointHandlerMapping(
|
||||
Environment environment, WebEndpointDiscoverer endpointDiscoverer,
|
||||
|
||||
Reference in New Issue
Block a user