Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package org.springframework.cloud.gateway.route;

import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
Expand Down Expand Up @@ -179,6 +180,42 @@ List<GatewayFilter> loadGatewayFilters(String id, List<FilterDefinition> filterD
}

private List<GatewayFilter> getFilters(RouteDefinition routeDefinition) {

// --- GH-3293: URI Path Syntactic Sugar ---
URI uri = routeDefinition.getUri();
if (uri != null && org.springframework.util.StringUtils.hasText(uri.getPath()) && !"/".equals(uri.getPath())) {

String path = uri.getPath();

// check if SetPath already exists to avoid duplication
boolean hasSetPath = routeDefinition.getFilters()
.stream()
.anyMatch(f -> "SetPath".equalsIgnoreCase(f.getName()));

if (!hasSetPath) {
// 1. Create the FilterDefinition programmatically
FilterDefinition sugar = new FilterDefinition();
sugar.setName("SetPath");
// SetPath expects a parameter named 'template'
sugar.addArg("template", path);

// Add it at the beginning of the filter chain
routeDefinition.getFilters().add(0, sugar);

// 2. Strip the path from the URI to prevent double-pathing
// (e.g., http://example.com/foo -> http://example.com)
URI strippedUri = org.springframework.web.util.UriComponentsBuilder.fromUri(uri)
.replacePath(null)
.build()
.toUri();
routeDefinition.setUri(strippedUri);
}
}
// --- END GH-3293 ---

// ... existing code follows (List<GatewayFilter> filters = new ArrayList<>();
// etc.)

List<GatewayFilter> filters = new ArrayList<>();
Objects.requireNonNull(routeDefinition.getId(), "Route id must be set");
// TODO: support option to apply defaults after route specific filters?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,41 @@ public void contextLoadsAndApplyRouteIdToRetryFilter() {
}).expectComplete().verify();
}

@Test
public void uriWithMappingShouldAddSetPathFilter() {
// 1. Setup
List<RoutePredicateFactory> predicates = Arrays.asList(new HostRoutePredicateFactory());
List<GatewayFilterFactory> gatewayFilterFactories = Arrays
.asList(new org.springframework.cloud.gateway.filter.factory.SetPathGatewayFilterFactory());

GatewayProperties gatewayProperties = new GatewayProperties();

// Standard way to create the definition
RouteDefinition definition = new RouteDefinition();
definition.setId("sugar_test");
definition.setUri(URI.create("https://example.com/foo/bar"));
definition.setPredicates(Arrays.asList(new PredicateDefinition("Host=*.example.com")));

gatewayProperties.setRoutes(Arrays.asList(definition));

PropertiesRouteDefinitionLocator routeDefinitionLocator = new PropertiesRouteDefinitionLocator(
gatewayProperties);

// 2. Initialize the Locator
RouteDefinitionRouteLocator routeDefinitionRouteLocator = new RouteDefinitionRouteLocator(
new CompositeRouteDefinitionLocator(Flux.just(routeDefinitionLocator)), predicates,
gatewayFilterFactories, gatewayProperties, new ConfigurationService(null, () -> null, () -> null));

// 3. Verify
StepVerifier.create(routeDefinitionRouteLocator.getRoutes()).assertNext(route -> {
assertThat(route.getUri().toString()).isEqualTo("https://example.com:443");

List<GatewayFilter> filters = route.getFilters();
assertThat(filters).hasSize(1);
assertThat(getFilterClassName(filters.get(0))).contains("SetPath");
}).expectComplete().verify();
}

private List<RouteDefinition> containsInvalidRoutes() {
RouteDefinition foo = new RouteDefinition();
foo.setId("foo");
Expand Down