From a3704f0614fed3dcd54a182982e320aed72358a2 Mon Sep 17 00:00:00 2001 From: Yanming Zhou Date: Tue, 27 Jul 2021 17:54:47 +0800 Subject: [PATCH] Support regex expression for @PathVariable (#577) Fix gh-576 --- docs/src/main/asciidoc/spring-cloud-openfeign.adoc | 3 +++ .../annotation/PathVariableParameterProcessor.java | 4 +++- .../openfeign/support/SpringMvcContractTests.java | 13 +++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/src/main/asciidoc/spring-cloud-openfeign.adoc b/docs/src/main/asciidoc/spring-cloud-openfeign.adoc index b0cc5aee..0bbc38d2 100644 --- a/docs/src/main/asciidoc/spring-cloud-openfeign.adoc +++ b/docs/src/main/asciidoc/spring-cloud-openfeign.adoc @@ -52,6 +52,9 @@ public interface StoreClient { @RequestMapping(method = RequestMethod.POST, value = "/stores/{storeId}", consumes = "application/json") Store update(@PathVariable("storeId") Long storeId, Store store); + + @RequestMapping(method = RequestMethod.DELETE, value = "/stores/{storeId:\\d+}") + void delete(@PathVariable Long storeId); } ---- diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/annotation/PathVariableParameterProcessor.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/annotation/PathVariableParameterProcessor.java index fdfb31a3..80741ee7 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/annotation/PathVariableParameterProcessor.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/annotation/PathVariableParameterProcessor.java @@ -34,6 +34,7 @@ import static feign.Util.emptyToNull; * * @author Jakub Narloch * @author Abhijit Sarkar + * @author Yanming Zhou * @see AnnotatedParameterProcessor */ public class PathVariableParameterProcessor implements AnnotatedParameterProcessor { @@ -54,7 +55,8 @@ public class PathVariableParameterProcessor implements AnnotatedParameterProcess MethodMetadata data = context.getMethodMetadata(); String varName = '{' + name + '}'; - if (!data.template().url().contains(varName) && !searchMapValues(data.template().queries(), varName) + String varNameRegex = ".*\\{" + name + "(:[^}]+)?\\}.*"; + if (!data.template().url().matches(varNameRegex) && !searchMapValues(data.template().queries(), varName) && !searchMapValues(data.template().headers(), varName)) { data.formParams().add(name); } diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/SpringMvcContractTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/SpringMvcContractTests.java index 7f6d7ad7..69b25f6f 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/SpringMvcContractTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/SpringMvcContractTests.java @@ -130,6 +130,16 @@ public class SpringMvcContractTests { assertThat(data.template().decodeSlash()).isTrue(); } + @Test + public void testProcessAnnotationOnMethod_Simple_RegexPathVariable() throws Exception { + Method method = TestTemplate_Simple.class.getDeclaredMethod("getTestWithDigitalId", String.class); + MethodMetadata data = contract.parseAndValidateMetadata(method.getDeclaringClass(), method); + + assertThat(data.template().url()).isEqualTo("/test/{id:\\d+}"); + assertThat(data.template().method()).isEqualTo("GET"); + assertThat(data.formParams()).isEmpty(); + } + @Test public void testProcessAnnotationOnMethod_Simple_SlashEncoded() throws Exception { contract = new SpringMvcContract(Collections.emptyList(), getConversionService(), false); @@ -588,6 +598,9 @@ public class SpringMvcContractTests { @RequestMapping(value = "/test/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) ResponseEntity getTest(@PathVariable("id") String id); + @GetMapping("/test/{id:\\d+}") + ResponseEntity getTestWithDigitalId(@PathVariable("id") String id); + @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) TestObject getTest();