mirror of
https://github.com/spring-projects/spring-boot.git
synced 2026-10-04 08:19:50 +00:00
Polish "Strip query string from Cloud Foundry reactive links base URL"
This commit polishes the proposed test for the WebFlux Cloud Foundry endpoint. To protect against future regressions, it also adds tests for the general purpose links endpoints (WebFlux, Web MVC, and Jersey) and for the Web MVC Cloud Foundry endpoint. See gh-50008
This commit is contained in:
+29
-27
@@ -146,47 +146,27 @@ class CloudFoundryWebFluxEndpointIntegrationTests {
|
||||
.jsonPath("_links.length()")
|
||||
.isEqualTo(5)
|
||||
.jsonPath("_links.self.href")
|
||||
.isNotEmpty()
|
||||
.value(isLinkTo("/cfApplication"))
|
||||
.jsonPath("_links.self.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.info.href")
|
||||
.isNotEmpty()
|
||||
.value(isLinkTo("/cfApplication/info"))
|
||||
.jsonPath("_links.info.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.env.href")
|
||||
.isNotEmpty()
|
||||
.value(isLinkTo("/cfApplication/env"))
|
||||
.jsonPath("_links.env.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.test.href")
|
||||
.isNotEmpty()
|
||||
.value(isLinkTo("/cfApplication/test"))
|
||||
.jsonPath("_links.test.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.test-part.href")
|
||||
.isNotEmpty()
|
||||
.value(isLinkTo("/cfApplication/test/{part}"))
|
||||
.jsonPath("_links.test-part.templated")
|
||||
.isEqualTo(true)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void linksToOtherEndpointsWithQueryStringShouldNotContainQueryInHref() {
|
||||
given(this.tokenValidator.validate(any())).willReturn(Mono.empty());
|
||||
given(this.securityService.getAccessLevel(any(), eq("app-id"))).willReturn(Mono.just(AccessLevel.FULL));
|
||||
this.contextRunner.run(withWebTestClient((client) -> client.get()
|
||||
.uri("/cfApplication?x=1")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken())
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody()
|
||||
.jsonPath("_links.self.href")
|
||||
.value((href) -> assertThat((String) href).doesNotContain("?").endsWith("/cfApplication"))
|
||||
.jsonPath("_links.info.href")
|
||||
.value((href) -> assertThat((String) href).doesNotContain("?").endsWith("/cfApplication/info"))
|
||||
.jsonPath("_links.env.href")
|
||||
.value((href) -> assertThat((String) href).doesNotContain("?").endsWith("/cfApplication/env"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void linksToOtherEndpointsForbidden() {
|
||||
CloudFoundryAuthorizationException exception = new CloudFoundryAuthorizationException(Reason.INVALID_TOKEN,
|
||||
@@ -216,11 +196,11 @@ class CloudFoundryWebFluxEndpointIntegrationTests {
|
||||
.jsonPath("_links.length()")
|
||||
.isEqualTo(2)
|
||||
.jsonPath("_links.self.href")
|
||||
.isNotEmpty()
|
||||
.value(isLinkTo("/cfApplication"))
|
||||
.jsonPath("_links.self.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.info.href")
|
||||
.isNotEmpty()
|
||||
.value(isLinkTo("/cfApplication/info"))
|
||||
.jsonPath("_links.info.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.env")
|
||||
@@ -231,12 +211,34 @@ class CloudFoundryWebFluxEndpointIntegrationTests {
|
||||
.doesNotExist()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenRequestHasAQueryStringLinksToOtherEndpointsDoNotHaveAQueryString() {
|
||||
given(this.tokenValidator.validate(any())).willReturn(Mono.empty());
|
||||
given(this.securityService.getAccessLevel(any(), eq("app-id"))).willReturn(Mono.just(AccessLevel.RESTRICTED));
|
||||
this.contextRunner.run(withWebTestClient((client) -> client.get()
|
||||
.uri("/cfApplication?x=1")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken())
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody()
|
||||
.jsonPath("_links.self.href")
|
||||
.value(isLinkTo("/cfApplication"))
|
||||
.jsonPath("_links.info.href")
|
||||
.value(isLinkTo("/cfApplication/info"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void unknownEndpointsAreForbidden() {
|
||||
this.contextRunner.run(withWebTestClient(
|
||||
(client) -> client.get().uri("/cfApplication/unknown").exchange().expectStatus().isForbidden()));
|
||||
}
|
||||
|
||||
private Consumer<Object> isLinkTo(String target) {
|
||||
return (href) -> assertThat(href).asString().doesNotContain("?").endsWith(target);
|
||||
}
|
||||
|
||||
private ContextConsumer<AssertableReactiveWebApplicationContext> withWebTestClient(
|
||||
Consumer<WebTestClient> clientConsumer) {
|
||||
return (context) -> {
|
||||
|
||||
+30
-7
@@ -58,6 +58,7 @@ 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;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
@@ -133,23 +134,23 @@ class CloudFoundryMvcWebEndpointIntegrationTests {
|
||||
.jsonPath("_links.length()")
|
||||
.isEqualTo(5)
|
||||
.jsonPath("_links.self.href")
|
||||
.isNotEmpty()
|
||||
.value(isLinkTo("/cfApplication"))
|
||||
.jsonPath("_links.self.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.info.href")
|
||||
.isNotEmpty()
|
||||
.value(isLinkTo("/cfApplication/info"))
|
||||
.jsonPath("_links.info.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.env.href")
|
||||
.isNotEmpty()
|
||||
.value(isLinkTo("/cfApplication/env"))
|
||||
.jsonPath("_links.env.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.test.href")
|
||||
.isNotEmpty()
|
||||
.value(isLinkTo("/cfApplication/test"))
|
||||
.jsonPath("_links.test.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.test-part.href")
|
||||
.isNotEmpty()
|
||||
.value(isLinkTo("/cfApplication/test/{part}"))
|
||||
.jsonPath("_links.test-part.templated")
|
||||
.isEqualTo(true));
|
||||
}
|
||||
@@ -184,11 +185,11 @@ class CloudFoundryMvcWebEndpointIntegrationTests {
|
||||
.jsonPath("_links.length()")
|
||||
.isEqualTo(2)
|
||||
.jsonPath("_links.self.href")
|
||||
.isNotEmpty()
|
||||
.value(isLinkTo("/cfApplication"))
|
||||
.jsonPath("_links.self.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.info.href")
|
||||
.isNotEmpty()
|
||||
.value(isLinkTo("/cfApplication/info"))
|
||||
.jsonPath("_links.info.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.env")
|
||||
@@ -199,6 +200,24 @@ class CloudFoundryMvcWebEndpointIntegrationTests {
|
||||
.doesNotExist());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenRequestHasAQueryStringLinksToOtherEndpointsDoNotHaveAQueryString() {
|
||||
given(this.securityService.getAccessLevel(any(), eq("app-id"))).willReturn(AccessLevel.RESTRICTED);
|
||||
load(TestEndpointConfiguration.class,
|
||||
(client) -> client.get()
|
||||
.uri("/cfApplication?x=1")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken())
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody()
|
||||
.jsonPath("_links.self.href")
|
||||
.value(isLinkTo("/cfApplication"))
|
||||
.jsonPath("_links.info.href")
|
||||
.value(isLinkTo("/cfApplication/info")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void unknownEndpointsAreForbidden() {
|
||||
load(TestEndpointConfiguration.class,
|
||||
@@ -210,6 +229,10 @@ class CloudFoundryMvcWebEndpointIntegrationTests {
|
||||
.isForbidden());
|
||||
}
|
||||
|
||||
private Consumer<Object> isLinkTo(String target) {
|
||||
return (href) -> assertThat(href).asString().doesNotContain("?").endsWith(target);
|
||||
}
|
||||
|
||||
private void load(Class<?> configuration, Consumer<WebTestClient> clientConsumer) {
|
||||
BiConsumer<ApplicationContext, WebTestClient> consumer = (context, client) -> clientConsumer.accept(client);
|
||||
new WebApplicationContextRunner(AnnotationConfigServletWebServerApplicationContext::new)
|
||||
|
||||
+32
-3
@@ -162,15 +162,40 @@ public abstract class AbstractWebEndpointIntegrationTests<T extends Configurable
|
||||
.jsonPath("_links.length()")
|
||||
.isEqualTo(3)
|
||||
.jsonPath("_links.self.href")
|
||||
.isNotEmpty()
|
||||
.value(isLinkTo("/endpoints"))
|
||||
.jsonPath("_links.self.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.test.href")
|
||||
.isNotEmpty()
|
||||
.value(isLinkTo("/endpoints/test"))
|
||||
.jsonPath("_links.test.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.test-part.href")
|
||||
.isNotEmpty()
|
||||
.value(isLinkTo("/endpoints/test/{part}"))
|
||||
.jsonPath("_links.test-part.templated")
|
||||
.isEqualTo(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenRequestHasAQueryStringLinksToOtherEndpointsDoNotHaveAQueryString() {
|
||||
load(TestEndpointConfiguration.class,
|
||||
(client) -> client.get()
|
||||
.uri("?a=alpha")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody()
|
||||
.jsonPath("_links.length()")
|
||||
.isEqualTo(3)
|
||||
.jsonPath("_links.self.href")
|
||||
.value(isLinkTo("/endpoints"))
|
||||
.jsonPath("_links.self.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.test.href")
|
||||
.value(isLinkTo("/endpoints/test"))
|
||||
.jsonPath("_links.test.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.test-part.href")
|
||||
.value(isLinkTo("/endpoints/test/{part}"))
|
||||
.jsonPath("_links.test-part.templated")
|
||||
.isEqualTo(true));
|
||||
}
|
||||
@@ -668,6 +693,10 @@ public abstract class AbstractWebEndpointIntegrationTests<T extends Configurable
|
||||
(client) -> client.get().uri("/customstatus").exchange().expectStatus().isEqualTo(234));
|
||||
}
|
||||
|
||||
private Consumer<Object> isLinkTo(String target) {
|
||||
return (href) -> assertThat(href).asString().doesNotContain("?").endsWith(target);
|
||||
}
|
||||
|
||||
protected abstract int getPort(T context);
|
||||
|
||||
protected void validateErrorBody(WebTestClient.BodyContentSpec body, HttpStatus status, String path,
|
||||
|
||||
Reference in New Issue
Block a user