Skip to content

Commit bf275ec

Browse files
committed
Add docs. Add more tests. Reformat code.
1 parent 1c22ebe commit bf275ec

File tree

5 files changed

+89
-16
lines changed

5 files changed

+89
-16
lines changed

docs/modules/ROOT/pages/spring-cloud-openfeign.adoc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,12 @@ public class CustomConfiguration {
288288
}
289289
----
290290

291-
TIP: By default, Feign clients do not encode slash `/` characters. You can change this behaviour, by setting the value of `spring.cloud.openfeign.client.decodeSlash` to `false`.
291+
TIP: By default, Feign clients do not encode slash `/` characters. You can change this behaviour, by setting the value of `spring.cloud.openfeign.client.decode-slash` to `false`.
292+
293+
294+
TIP: By default, Feign clients do not remove trailing slash `/` characters from the request path.
295+
You can change this behaviour, by setting the value of `spring.cloud.openfeign.client.remove-trailing-slash` to `true`.
296+
Trailing slash removal from the request path is going to be made the default behaviour in the next major release.
292297

293298
[[springencoder-configuration]]
294299
==== `SpringEncoder` configuration

docs/modules/ROOT/partials/_configprops.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
|spring.cloud.openfeign.client.default-config | `+++default+++` |
7474
|spring.cloud.openfeign.client.default-to-properties | `+++true+++` |
7575
|spring.cloud.openfeign.client.refresh-enabled | `+++false+++` | Enables options value refresh capability for Feign.
76+
|spring.cloud.openfeign.client.remove-trailing-slash | `+++false+++` | If {@code true}, trailing slashes at the end of request urls will be removed.
7677
|spring.cloud.openfeign.compression.request.content-encoding-types | | The list of content encodings (applicable encodings depend on the used client).
7778
|spring.cloud.openfeign.compression.request.enabled | `+++false+++` | Enables the request sent by Feign to be compressed.
7879
|spring.cloud.openfeign.compression.request.mime-types | `+++[text/xml, application/xml, application/json]+++` | The list of supported mime types.

spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientProperties.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,7 @@ public class FeignClientProperties {
6262
private boolean decodeSlash = true;
6363

6464
/**
65-
* If {@code true}, trailing slashes at the end
66-
* of request urls will be removed.
65+
* If {@code true}, trailing slashes at the end of request urls will be removed.
6766
*/
6867
private boolean removeTrailingSlash;
6968

@@ -117,8 +116,8 @@ public boolean equals(Object o) {
117116
}
118117
FeignClientProperties that = (FeignClientProperties) o;
119118
return defaultToProperties == that.defaultToProperties && Objects.equals(defaultConfig, that.defaultConfig)
120-
&& Objects.equals(config, that.config) && Objects.equals(decodeSlash, that.decodeSlash)
121-
&& Objects.equals(removeTrailingSlash, that.removeTrailingSlash);
119+
&& Objects.equals(config, that.config) && Objects.equals(decodeSlash, that.decodeSlash)
120+
&& Objects.equals(removeTrailingSlash, that.removeTrailingSlash);
122121
}
123122

124123
@Override

spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringMvcContract.java

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -134,10 +134,12 @@ public SpringMvcContract(List<AnnotatedParameterProcessor> annotatedParameterPro
134134
/**
135135
* Creates a {@link SpringMvcContract} based on annotatedParameterProcessors,
136136
* conversionService and decodeSlash value.
137-
* @param annotatedParameterProcessors list of {@link AnnotatedParameterProcessor} objects used to resolve parameters
137+
* @param annotatedParameterProcessors list of {@link AnnotatedParameterProcessor}
138+
* objects used to resolve parameters
138139
* @param conversionService {@link ConversionService} used for type conversion
139140
* @param decodeSlash indicates whether slashes should be decoded
140-
* @deprecated in favour of {@link SpringMvcContract#SpringMvcContract(List, ConversionService, FeignClientProperties)}
141+
* @deprecated in favour of
142+
* {@link SpringMvcContract#SpringMvcContract(List, ConversionService, FeignClientProperties)}
141143
*/
142144
@Deprecated
143145
public SpringMvcContract(List<AnnotatedParameterProcessor> annotatedParameterProcessors,
@@ -148,15 +150,17 @@ public SpringMvcContract(List<AnnotatedParameterProcessor> annotatedParameterPro
148150
/**
149151
* Creates a {@link SpringMvcContract} based on annotatedParameterProcessors,
150152
* conversionService and decodeSlash value.
151-
* @param annotatedParameterProcessors list of {@link AnnotatedParameterProcessor} objects used to resolve parameters
153+
* @param annotatedParameterProcessors list of {@link AnnotatedParameterProcessor}
154+
* objects used to resolve parameters
152155
* @param conversionService {@link ConversionService} used for type conversion
153156
* @param decodeSlash indicates whether slashes should be decoded
154157
* @param removeTrailingSlash indicates whether trailing slashes should be removed
155-
* @deprecated in favour of {@link SpringMvcContract#SpringMvcContract(List, ConversionService, FeignClientProperties)}
158+
* @deprecated in favour of
159+
* {@link SpringMvcContract#SpringMvcContract(List, ConversionService, FeignClientProperties)}
156160
*/
157161
@Deprecated
158162
public SpringMvcContract(List<AnnotatedParameterProcessor> annotatedParameterProcessors,
159-
ConversionService conversionService, boolean decodeSlash, boolean removeTrailingSlash) {
163+
ConversionService conversionService, boolean decodeSlash, boolean removeTrailingSlash) {
160164
Assert.notNull(annotatedParameterProcessors, "Parameter processors can not be null.");
161165
Assert.notNull(conversionService, "ConversionService can not be null.");
162166

@@ -171,10 +175,10 @@ public SpringMvcContract(List<AnnotatedParameterProcessor> annotatedParameterPro
171175
}
172176

173177
public SpringMvcContract(List<AnnotatedParameterProcessor> annotatedParameterProcessors,
174-
ConversionService conversionService, FeignClientProperties feignClientProperties) {
178+
ConversionService conversionService, FeignClientProperties feignClientProperties) {
175179
this(annotatedParameterProcessors, conversionService,
176-
feignClientProperties == null || feignClientProperties.isDecodeSlash(),
177-
feignClientProperties != null && feignClientProperties.isRemoveTrailingSlash());
180+
feignClientProperties == null || feignClientProperties.isDecodeSlash(),
181+
feignClientProperties != null && feignClientProperties.isRemoveTrailingSlash());
178182
}
179183

180184
private static TypeDescriptor createTypeDescriptor(Method method, int paramIndex) {

spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/SpringMvcContractTests.java

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.junit.jupiter.api.Test;
3737

3838
import org.springframework.cloud.openfeign.CollectionFormat;
39+
import org.springframework.cloud.openfeign.FeignClientProperties;
3940
import org.springframework.cloud.openfeign.SpringQueryMap;
4041
import org.springframework.core.convert.ConversionService;
4142
import org.springframework.data.domain.Page;
@@ -189,8 +190,23 @@ void testProcessAnnotations_SimpleNoPath() throws Exception {
189190
}
190191

191192
@Test
192-
void testProcessAnnotations_SimplePathIsOnlyASlash() throws Exception {
193-
Method method = TestTemplate_Simple.class.getDeclaredMethod("getSlashPath", String.class);
193+
void testProcessAnnotations_SimplePathIsOnlyASlashWithParam() throws Exception {
194+
Method method = TestTemplate_Simple.class.getDeclaredMethod("getSlashPathWithParam", String.class);
195+
MethodMetadata data = contract.parseAndValidateMetadata(method.getDeclaringClass(), method);
196+
197+
assertThat(data.template().url()).isEqualTo("/?id=" + "{id}");
198+
assertThat(data.template().method()).isEqualTo("GET");
199+
assertThat(data.template().headers().get("Accept").iterator().next())
200+
.isEqualTo(MediaType.APPLICATION_JSON_VALUE);
201+
}
202+
203+
@Test
204+
void testProcessAnnotations_SimplePathIsOnlyASlashWithParamWithTrailingSlashRemoval() throws Exception {
205+
FeignClientProperties properties = new FeignClientProperties();
206+
properties.setRemoveTrailingSlash(true);
207+
contract = new SpringMvcContract(Collections.emptyList(), getConversionService(), properties);
208+
Method method = TestTemplate_Simple.class.getDeclaredMethod("getSlashPathWithParam", String.class);
209+
194210
MethodMetadata data = contract.parseAndValidateMetadata(method.getDeclaringClass(), method);
195211

196212
assertThat(data.template().url()).isEqualTo("/?id=" + "{id}");
@@ -284,6 +300,48 @@ void testProcessAnnotations_SimplePostMapping() throws Exception {
284300

285301
}
286302

303+
@Test
304+
void testProcessAnnotations_SimplePathIsOnlyASlashWithTrailingSlashRemoval() throws Exception {
305+
FeignClientProperties properties = new FeignClientProperties();
306+
properties.setRemoveTrailingSlash(true);
307+
contract = new SpringMvcContract(Collections.emptyList(), getConversionService(), properties);
308+
Method method = TestTemplate_Simple.class.getDeclaredMethod("getSlashPath");
309+
310+
MethodMetadata data = contract.parseAndValidateMetadata(method.getDeclaringClass(), method);
311+
312+
assertThat(data.template().url()).isEqualTo("/");
313+
assertThat(data.template().method()).isEqualTo("GET");
314+
assertThat(data.template().headers().get("Accept").iterator().next())
315+
.isEqualTo(MediaType.APPLICATION_JSON_VALUE);
316+
}
317+
318+
@Test
319+
void testProcessAnnotations_SimplePathHasTrailingSlash() throws Exception {
320+
Method method = TestTemplate_Simple.class.getDeclaredMethod("getTrailingSlash");
321+
322+
MethodMetadata data = contract.parseAndValidateMetadata(method.getDeclaringClass(), method);
323+
324+
assertThat(data.template().url()).isEqualTo("/test1/test2/");
325+
assertThat(data.template().method()).isEqualTo("GET");
326+
assertThat(data.template().headers().get("Accept").iterator().next())
327+
.isEqualTo(MediaType.APPLICATION_JSON_VALUE);
328+
}
329+
330+
@Test
331+
void testProcessAnnotations_SimplePathHasTrailingSlashWithTrailingSlashRemoval() throws Exception {
332+
FeignClientProperties properties = new FeignClientProperties();
333+
properties.setRemoveTrailingSlash(true);
334+
contract = new SpringMvcContract(Collections.emptyList(), getConversionService(), properties);
335+
Method method = TestTemplate_Simple.class.getDeclaredMethod("getTrailingSlash");
336+
337+
MethodMetadata data = contract.parseAndValidateMetadata(method.getDeclaringClass(), method);
338+
339+
assertThat(data.template().url()).isEqualTo("/test1/test2");
340+
assertThat(data.template().method()).isEqualTo("GET");
341+
assertThat(data.template().headers().get("Accept").iterator().next())
342+
.isEqualTo(MediaType.APPLICATION_JSON_VALUE);
343+
}
344+
287345
@Test
288346
void testProcessAnnotationsOnMethod_Advanced() throws Exception {
289347
Method method = TestTemplate_Advanced.class.getDeclaredMethod("getTest", String.class, String.class,
@@ -738,7 +796,13 @@ public interface TestTemplate_Simple {
738796
TestObject postMappingTest(@RequestBody TestObject object);
739797

740798
@GetMapping(value = "/", produces = MediaType.APPLICATION_JSON_VALUE)
741-
ResponseEntity<TestObject> getSlashPath(@RequestParam("id") String id);
799+
ResponseEntity<TestObject> getSlashPathWithParam(@RequestParam("id") String id);
800+
801+
@GetMapping(value = "/", produces = MediaType.APPLICATION_JSON_VALUE)
802+
ResponseEntity<TestObject> getSlashPath();
803+
804+
@GetMapping(value = "test1/test2/", produces = MediaType.APPLICATION_JSON_VALUE)
805+
ResponseEntity<TestObject> getTrailingSlash();
742806

743807
@GetMapping(path = "test", produces = MediaType.APPLICATION_JSON_VALUE)
744808
ResponseEntity<TestObject> getTestNoLeadingSlash(@RequestParam("name") String name);

0 commit comments

Comments
 (0)