9 changed files with 283 additions and 0 deletions
@ -0,0 +1,96 @@
@@ -0,0 +1,96 @@
|
||||
/* |
||||
* Copyright 2013-2023 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.cloud.gateway.filter.factory; |
||||
|
||||
import java.net.URI; |
||||
import java.util.Arrays; |
||||
import java.util.List; |
||||
|
||||
import reactor.core.publisher.Mono; |
||||
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilter; |
||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain; |
||||
import org.springframework.http.server.reactive.ServerHttpRequest; |
||||
import org.springframework.util.Assert; |
||||
import org.springframework.web.server.ServerWebExchange; |
||||
import org.springframework.web.util.UriComponentsBuilder; |
||||
|
||||
import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; |
||||
|
||||
/** |
||||
* @author Fredrich Ombico |
||||
*/ |
||||
public class RewriteRequestParameterGatewayFilterFactory |
||||
extends AbstractGatewayFilterFactory<RewriteRequestParameterGatewayFilterFactory.Config> { |
||||
|
||||
/** |
||||
* Replacement key. |
||||
*/ |
||||
public static final String REPLACEMENT_KEY = "replacement"; |
||||
|
||||
public RewriteRequestParameterGatewayFilterFactory() { |
||||
super(Config.class); |
||||
} |
||||
|
||||
@Override |
||||
public List<String> shortcutFieldOrder() { |
||||
return Arrays.asList(NAME_KEY, REPLACEMENT_KEY); |
||||
} |
||||
|
||||
@Override |
||||
public GatewayFilter apply(Config config) { |
||||
return new GatewayFilter() { |
||||
@Override |
||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { |
||||
ServerHttpRequest req = exchange.getRequest(); |
||||
|
||||
UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUri(req.getURI()); |
||||
if (req.getQueryParams().containsKey(config.getName())) { |
||||
uriComponentsBuilder.replaceQueryParam(config.getName(), config.getReplacement()); |
||||
} |
||||
|
||||
URI uri = uriComponentsBuilder.build().toUri(); |
||||
ServerHttpRequest request = req.mutate().uri(uri).build(); |
||||
|
||||
return chain.filter(exchange.mutate().request(request).build()); |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return filterToStringCreator(RewriteRequestParameterGatewayFilterFactory.this) |
||||
.append(config.getName(), config.replacement).toString(); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
public static class Config extends AbstractGatewayFilterFactory.NameConfig { |
||||
|
||||
private String replacement; |
||||
|
||||
public String getReplacement() { |
||||
return replacement; |
||||
} |
||||
|
||||
public Config setReplacement(String replacement) { |
||||
Assert.notNull(replacement, "replacement must not be null"); |
||||
this.replacement = replacement; |
||||
return this; |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
@ -0,0 +1,50 @@
@@ -0,0 +1,50 @@
|
||||
/* |
||||
* Copyright 2013-2023 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.cloud.gateway.filter.factory; |
||||
|
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
import org.springframework.boot.SpringBootConfiguration; |
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; |
||||
import org.springframework.boot.test.context.SpringBootTest; |
||||
import org.springframework.cloud.gateway.test.BaseWebClientTests; |
||||
import org.springframework.context.annotation.Import; |
||||
import org.springframework.test.annotation.DirtiesContext; |
||||
|
||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; |
||||
|
||||
/** |
||||
* @author Fredrich Ombico |
||||
*/ |
||||
@SpringBootTest(webEnvironment = RANDOM_PORT) |
||||
@DirtiesContext |
||||
class RewriteRequestParameterGatewayFilterFactoryIntegrationTests extends BaseWebClientTests { |
||||
|
||||
@Test |
||||
void rewriteRequestParameterFilterWorks() { |
||||
testClient.get().uri("/get?campaign=old").header("Host", "www.rewriterequestparameter.org").exchange() |
||||
.expectStatus().isOk().expectBody().jsonPath("$.args.size", "fall2023"); |
||||
} |
||||
|
||||
@EnableAutoConfiguration |
||||
@SpringBootConfiguration |
||||
@Import(DefaultTestConfig.class) |
||||
public static class TestConfig { |
||||
|
||||
} |
||||
|
||||
} |
@ -0,0 +1,102 @@
@@ -0,0 +1,102 @@
|
||||
/* |
||||
* Copyright 2013-2023 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.cloud.gateway.filter.factory; |
||||
|
||||
import java.net.URI; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
import org.junit.jupiter.api.Test; |
||||
import org.mockito.ArgumentCaptor; |
||||
import reactor.core.publisher.Mono; |
||||
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilter; |
||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain; |
||||
import org.springframework.http.HttpMethod; |
||||
import org.springframework.mock.http.server.reactive.MockServerHttpRequest; |
||||
import org.springframework.mock.web.server.MockServerWebExchange; |
||||
import org.springframework.util.MultiValueMap; |
||||
import org.springframework.web.server.ServerWebExchange; |
||||
import org.springframework.web.util.UriComponentsBuilder; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.mockito.Mockito.mock; |
||||
import static org.mockito.Mockito.when; |
||||
import static org.springframework.cloud.gateway.filter.factory.RewriteRequestParameterGatewayFilterFactory.Config; |
||||
|
||||
/** |
||||
* @author Fredrich Ombico |
||||
*/ |
||||
class RewriteRequestParameterGatewayFilterFactoryTests { |
||||
|
||||
@Test |
||||
void toStringFormat() { |
||||
Config config = new Config(); |
||||
config.setName("campaign"); |
||||
config.setReplacement("fall2023"); |
||||
GatewayFilter filter = new RewriteRequestParameterGatewayFilterFactory().apply(config); |
||||
assertThat(filter.toString()).contains("campaign").contains("fall2023"); |
||||
} |
||||
|
||||
@Test |
||||
void rewriteRequestParameterFilterWorks() { |
||||
testRewriteRequestParameterFilter("campaign", "fall2023", "size=small&campaign=old", |
||||
Map.of("size", List.of("small"), "campaign", List.of("fall2023"))); |
||||
} |
||||
|
||||
@Test |
||||
void rewriteRequestParameterFilterRewritesMultipleParamsWithSameName() { |
||||
testRewriteRequestParameterFilter("campaign", "fall2023", "campaign=fall&size=small&campaign=old", |
||||
Map.of("size", List.of("small"), "campaign", List.of("fall2023"))); |
||||
} |
||||
|
||||
@Test |
||||
void rewriteRequestParameterFilterDoesNotAddParamIfNameNotFound() { |
||||
testRewriteRequestParameterFilter("campaign", "winter2023", "color=green&sort=popular", |
||||
Map.of("color", List.of("green"), "sort", List.of("popular"))); |
||||
} |
||||
|
||||
@Test |
||||
void rewriteRequestParameterFilterWorksWithSpecialCharacters() { |
||||
testRewriteRequestParameterFilter("campaign", "black friday~(1.A-B_C!)", "campaign=old&color=green", |
||||
Map.of("campaign", List.of("black friday~(1.A-B_C!)"), "color", List.of("green"))); |
||||
} |
||||
|
||||
private void testRewriteRequestParameterFilter(String name, String replacement, String query, |
||||
Map<String, List<String>> expectedQueryParams) { |
||||
GatewayFilter filter = new RewriteRequestParameterGatewayFilterFactory() |
||||
.apply(config -> config.setReplacement(replacement).setName(name)); |
||||
|
||||
URI url = UriComponentsBuilder.fromUriString("http://localhost/get").query(query).build(true).toUri(); |
||||
MockServerHttpRequest request = MockServerHttpRequest.method(HttpMethod.GET, url).build(); |
||||
|
||||
ServerWebExchange exchange = MockServerWebExchange.from(request); |
||||
|
||||
GatewayFilterChain filterChain = mock(GatewayFilterChain.class); |
||||
|
||||
ArgumentCaptor<ServerWebExchange> captor = ArgumentCaptor.forClass(ServerWebExchange.class); |
||||
when(filterChain.filter(captor.capture())).thenReturn(Mono.empty()); |
||||
|
||||
filter.filter(exchange, filterChain); |
||||
|
||||
ServerWebExchange webExchange = captor.getValue(); |
||||
|
||||
MultiValueMap<String, String> actualQueryParams = webExchange.getRequest().getQueryParams(); |
||||
assertThat(actualQueryParams).containsExactlyInAnyOrderEntriesOf(expectedQueryParams); |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue