Skip to content

Commit e2eda6a

Browse files
committed
Add support for Spring Cloud Function Web. Fixes #1299
1 parent 2545498 commit e2eda6a

File tree

3 files changed

+39
-15
lines changed

3 files changed

+39
-15
lines changed

springdoc-openapi-common/src/main/java/org/springdoc/core/providers/impl/SpringCloudFunctionProvider.java

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@
1717
import io.swagger.v3.oas.models.responses.ApiResponse;
1818
import io.swagger.v3.oas.models.responses.ApiResponses;
1919
import org.apache.commons.lang3.ArrayUtils;
20+
import org.apache.commons.lang3.StringUtils;
2021
import org.springdoc.core.GenericResponseService;
2122
import org.springdoc.core.SpringDocAnnotationsUtils;
2223
import org.springdoc.core.SpringDocConfigProperties;
2324
import org.springdoc.core.annotations.RouterOperations;
2425
import org.springdoc.core.fn.RouterOperation;
2526
import org.springdoc.core.providers.CloudFunctionProvider;
2627

28+
import org.springframework.beans.factory.annotation.Value;
2729
import org.springframework.cloud.function.context.FunctionCatalog;
2830
import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper;
2931
import org.springframework.cloud.function.context.config.RoutingFunction;
@@ -83,6 +85,11 @@ public class SpringCloudFunctionProvider implements CloudFunctionProvider {
8385
*/
8486
private static final String[] defaultMediaTypes = new String[] { MediaType.APPLICATION_JSON_VALUE, MediaType.TEXT_PLAIN_VALUE };
8587

88+
/**
89+
* The spring cloud function prefix.
90+
*/
91+
@Value("${spring.cloud.function.web.path:}")
92+
private String prefix = "";
8693

8794
/**
8895
* Instantiates a new Spring cloud function provider.
@@ -95,7 +102,7 @@ public SpringCloudFunctionProvider(Optional<FunctionCatalog> functionCatalogOpti
95102
this.functionCatalogOptional = functionCatalogOptional;
96103
this.genericResponseService = genericResponseService;
97104
this.springDocConfigProperties = springDocConfigProperties;
98-
this.applicationContext=applicationContext;
105+
this.applicationContext = applicationContext;
99106
}
100107

101108
@Override
@@ -113,10 +120,19 @@ public List<RouterOperation> getRouterOperations(OpenAPI openAPI) {
113120
buildRequest(openAPI, name, function, requestMethod, routerOperation);
114121
ApiResponses apiResponses = buildResponses(openAPI, function, defaultMediaTypes);
115122
routerOperation.getOperationModel().responses(apiResponses);
116-
if (GET.equals(requestMethod))
117-
routerOperation.setPath(AntPathMatcher.DEFAULT_PATH_SEPARATOR + name + AntPathMatcher.DEFAULT_PATH_SEPARATOR + "{" + name + "}");
118-
else
119-
routerOperation.setPath(AntPathMatcher.DEFAULT_PATH_SEPARATOR + name);
123+
if (StringUtils.isEmpty(prefix)) {
124+
if (GET.equals(requestMethod))
125+
routerOperation.setPath(AntPathMatcher.DEFAULT_PATH_SEPARATOR + name + AntPathMatcher.DEFAULT_PATH_SEPARATOR + "{" + name + "}");
126+
else
127+
routerOperation.setPath(AntPathMatcher.DEFAULT_PATH_SEPARATOR + name);
128+
}
129+
else {
130+
if (GET.equals(requestMethod))
131+
routerOperation.setPath(prefix + AntPathMatcher.DEFAULT_PATH_SEPARATOR + name + AntPathMatcher.DEFAULT_PATH_SEPARATOR + "{" + name + "}");
132+
else
133+
routerOperation.setPath(prefix + AntPathMatcher.DEFAULT_PATH_SEPARATOR + name);
134+
}
135+
120136
RouterOperation userRouterOperation = this.getRouterFunctionPaths(name, requestMethod);
121137
if (userRouterOperation != null)
122138
mergeRouterOperation(routerOperation, userRouterOperation);
@@ -131,7 +147,10 @@ else if (function.isConsumer()) {
131147
apiResponse.setContent(new Content());
132148
apiResponses.put(String.valueOf(HttpStatus.ACCEPTED.value()), apiResponse.description(HttpStatus.ACCEPTED.getReasonPhrase()));
133149
routerOperation.getOperationModel().responses(apiResponses);
134-
routerOperation.setPath(AntPathMatcher.DEFAULT_PATH_SEPARATOR + name);
150+
if (StringUtils.isEmpty(prefix))
151+
routerOperation.setPath(AntPathMatcher.DEFAULT_PATH_SEPARATOR + name);
152+
else
153+
routerOperation.setPath(prefix + AntPathMatcher.DEFAULT_PATH_SEPARATOR + name);
135154
RouterOperation userRouterOperation = this.getRouterFunctionPaths(name, requestMethod);
136155
if (userRouterOperation != null)
137156
mergeRouterOperation(routerOperation, userRouterOperation);
@@ -142,7 +161,10 @@ else if (function.isSupplier()) {
142161
RouterOperation routerOperation = buildRouterOperation(name, " supplier", requestMethod, routerOperationList);
143162
ApiResponses apiResponses = buildResponses(openAPI, function, new String[] { springDocConfigProperties.getDefaultProducesMediaType() });
144163
routerOperation.getOperationModel().responses(apiResponses);
145-
routerOperation.setPath(AntPathMatcher.DEFAULT_PATH_SEPARATOR + name);
164+
if (StringUtils.isEmpty(prefix))
165+
routerOperation.setPath(AntPathMatcher.DEFAULT_PATH_SEPARATOR + name);
166+
else
167+
routerOperation.setPath(prefix + AntPathMatcher.DEFAULT_PATH_SEPARATOR + name);
146168
RouterOperation userRouterOperation = this.getRouterFunctionPaths(name, requestMethod);
147169
if (userRouterOperation != null)
148170
mergeRouterOperation(routerOperation, userRouterOperation);

springdoc-openapi-webflux-core/src/test/java/test/org/springdoc/api/app154/SpringDocApp154Test.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@
2929
import org.springframework.boot.autoconfigure.SpringBootApplication;
3030
import org.springframework.context.annotation.Bean;
3131
import org.springframework.context.annotation.ComponentScan;
32+
import org.springframework.test.context.TestPropertySource;
3233

34+
@TestPropertySource(properties = "spring.cloud.function.web.path=/toto")
3335
public class SpringDocApp154Test extends AbstractSpringDocFunctionTest {
3436

3537
@SpringBootApplication

springdoc-openapi-webflux-core/src/test/resources/results/app154.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
}
1212
],
1313
"paths": {
14-
"/lowercase": {
14+
"/toto/lowercase": {
1515
"post": {
1616
"description": "lowercase function",
1717
"operationId": "lowercase_POST",
@@ -60,7 +60,7 @@
6060
}
6161
}
6262
},
63-
"/lowercase/{lowercase}": {
63+
"/toto/lowercase/{lowercase}": {
6464
"get": {
6565
"description": "lowercase function",
6666
"operationId": "lowercase_GET",
@@ -102,7 +102,7 @@
102102
}
103103
}
104104
},
105-
"/reverseString": {
105+
"/toto/reverseString": {
106106
"post": {
107107
"description": "reverseString function",
108108
"operationId": "reverseString_POST",
@@ -139,7 +139,7 @@
139139
}
140140
}
141141
},
142-
"/reverseString/{reverseString}": {
142+
"/toto/reverseString/{reverseString}": {
143143
"get": {
144144
"description": "reverseString function",
145145
"operationId": "reverseString_GET",
@@ -172,7 +172,7 @@
172172
}
173173
}
174174
},
175-
"/titi": {
175+
"/toto/titi": {
176176
"get": {
177177
"description": "titi supplier",
178178
"operationId": "titi_GET",
@@ -190,7 +190,7 @@
190190
}
191191
}
192192
},
193-
"/uppercase": {
193+
"/toto/uppercase": {
194194
"post": {
195195
"description": "uppercase function",
196196
"operationId": "uppercase_POST",
@@ -227,7 +227,7 @@
227227
}
228228
}
229229
},
230-
"/uppercase/{uppercase}": {
230+
"/toto/uppercase/{uppercase}": {
231231
"get": {
232232
"description": "uppercase function",
233233
"operationId": "uppercase_GET",
@@ -260,7 +260,7 @@
260260
}
261261
}
262262
},
263-
"/words": {
263+
"/toto/words": {
264264
"get": {
265265
"description": "words supplier",
266266
"operationId": "words_GET",

0 commit comments

Comments
 (0)