Test invalid URI raises early error before /refresh

When an invalid URI is configured in a routeDefinition, the endpoint for saving a route returns 201 Created response. However, the invalid route finally fails after calling `/refresh` endpoint.

If the developer configures more than one route, and the refresh fail because one route, all the routes are not persisted, leaving an inconsistent state

Fixes gh-2881
This commit is contained in:
Ignacio Lozano
2023-03-06 13:16:13 +01:00
committed by spencergibb
parent 5d8c2cf898
commit a4182c04c8
2 changed files with 42 additions and 0 deletions

View File

@@ -43,6 +43,7 @@ import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@@ -156,6 +157,18 @@ public class AbstractGatewayControllerEndpoint implements ApplicationEventPublis
else if (!unavailablePredicatesDefinitions.isEmpty()) {
handleUnavailableDefinition(PredicateDefinition.class.getSimpleName(), unavailablePredicatesDefinitions);
}
validateRouteUri(routeDefinition.getUri());
}
private void validateRouteUri(URI uri) {
if (uri == null) {
handleError("The URI can not be empty");
}
if (!StringUtils.hasText(uri.getScheme())) {
handleError("The URI format [%s] is incorrect, scheme can not be empty".formatted(uri));
}
}
private void handleUnavailableDefinition(String simpleName, Set<String> unavailableDefinitions) {
@@ -164,6 +177,11 @@ public class AbstractGatewayControllerEndpoint implements ApplicationEventPublis
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, errorMessage);
}
private void handleError(String errorMessage) {
log.warn(errorMessage);
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, errorMessage);
}
private boolean isAvailable(FilterDefinition filterDefinition) {
return GatewayFilters.stream()
.anyMatch(gatewayFilterFactory -> filterDefinition.getName().equals(gatewayFilterFactory.name()));

View File

@@ -209,6 +209,30 @@ public class GatewayControllerEndpointTests {
.isEqualTo("Invalid FilterDefinition: [NotExistingFilter]");
}
@Test
public void testPostRouteWithUriWithoutScheme() {
RouteDefinition testRouteDefinition = new RouteDefinition();
testRouteDefinition.setUri(URI.create("example.org"));
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/routes/no-scheme-test-route")
.accept(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(testRouteDefinition)).exchange()
.expectStatus().isBadRequest().expectBody().jsonPath("$.message")
.isEqualTo("The URI format [example.org] is incorrect, scheme can not be empty");
}
@Test
public void testPostRouteWithUri() {
RouteDefinition testRouteDefinition = new RouteDefinition();
testRouteDefinition.setUri(null);
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/routes/no-scheme-test-route")
.accept(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(testRouteDefinition)).exchange()
.expectStatus().isBadRequest().expectBody().jsonPath("$.message")
.isEqualTo("The URI can not be empty");
}
@Test
public void testPostRouteWithNotExistingPredicate() {