Skip to content

Commit b57f488

Browse files
committed
Merge branch 'mc1arke-method-filtering'
2 parents 46483c9 + 5057671 commit b57f488

File tree

22 files changed

+566
-48
lines changed

22 files changed

+566
-48
lines changed

springdoc-openapi-common/src/main/java/org/springdoc/api/AbstractOpenApiResource.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
import org.springdoc.core.GenericParameterService;
8080
import org.springdoc.core.GenericResponseService;
8181
import org.springdoc.core.MethodAttributes;
82+
import org.springdoc.core.filters.OpenApiMethodFilter;
8283
import org.springdoc.core.OpenAPIService;
8384
import org.springdoc.core.OperationService;
8485
import org.springdoc.core.SpringDocConfigProperties;
@@ -179,6 +180,11 @@ public abstract class AbstractOpenApiResource extends SpecFilter {
179180
*/
180181
private final Optional<List<OperationCustomizer>> operationCustomizers;
181182

183+
/**
184+
* The method filters to use.
185+
*/
186+
private final Optional<List<OpenApiMethodFilter>> methodFilters;
187+
182188
/**
183189
* The Ant path matcher.
184190
*/
@@ -222,6 +228,7 @@ public abstract class AbstractOpenApiResource extends SpecFilter {
222228
* @param operationParser the operation parser
223229
* @param operationCustomizers the operation customizers
224230
* @param openApiCustomisers the open api customisers
231+
* @param methodFilters the method filters
225232
* @param springDocConfigProperties the spring doc config properties
226233
* @param springDocProviders the spring doc providers
227234
*/
@@ -230,6 +237,7 @@ protected AbstractOpenApiResource(String groupName, ObjectFactory<OpenAPIService
230237
GenericResponseService responseBuilder, OperationService operationParser,
231238
Optional<List<OperationCustomizer>> operationCustomizers,
232239
Optional<List<OpenApiCustomiser>> openApiCustomisers,
240+
Optional<List<OpenApiMethodFilter>> methodFilters,
233241
SpringDocConfigProperties springDocConfigProperties, SpringDocProviders springDocProviders) {
234242
super();
235243
this.groupName = Objects.requireNonNull(groupName, "groupName");
@@ -239,6 +247,7 @@ protected AbstractOpenApiResource(String groupName, ObjectFactory<OpenAPIService
239247
this.responseBuilder = responseBuilder;
240248
this.operationParser = operationParser;
241249
this.openApiCustomisers = openApiCustomisers;
250+
this.methodFilters = methodFilters;
242251
this.springDocProviders = springDocProviders;
243252
//add the default customizers
244253
Map<String, OpenApiCustomiser> existingOpenApiCustomisers = openAPIService.getContext().getBeansOfType(OpenApiCustomiser.class);
@@ -650,10 +659,24 @@ protected void getRouterFunctionPaths(String beanName, AbstractRouterFunctionVis
650659
* @return the boolean
651660
*/
652661
protected boolean isFilterCondition(HandlerMethod handlerMethod, String operationPath, String[] produces, String[] consumes, String[] headers) {
653-
return isPackageToScan(handlerMethod.getBeanType().getPackage())
662+
return isMethodToFilter(handlerMethod)
663+
&& isPackageToScan(handlerMethod.getBeanType().getPackage())
654664
&& isFilterCondition(operationPath, produces, consumes, headers);
655665
}
656666

667+
/**
668+
* Is target method suitable for inclusion in current documentation/
669+
*
670+
* @param handlerMethod the method to check
671+
* @return whether the method should be included in the current OpenAPI definition
672+
*/
673+
protected boolean isMethodToFilter(HandlerMethod handlerMethod) {
674+
return this.methodFilters
675+
.map(Collection::stream)
676+
.map(stream -> stream.allMatch(m -> m.isMethodToInclude(handlerMethod.getMethod())))
677+
.orElse(true);
678+
}
679+
657680
/**
658681
* Is condition to match boolean.
659682
*

springdoc-openapi-common/src/main/java/org/springdoc/core/GroupedOpenApi.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import org.springdoc.core.customizers.OpenApiCustomiser;
2929
import org.springdoc.core.customizers.OperationCustomizer;
30+
import org.springdoc.core.filters.OpenApiMethodFilter;
3031

3132
import org.springframework.util.CollectionUtils;
3233

@@ -88,6 +89,11 @@ public class GroupedOpenApi {
8889
*/
8990
private final List<String> consumesToMatch;
9091

92+
/**
93+
* The method filters to use.
94+
*/
95+
private final List<OpenApiMethodFilter> openApiMethodFilters;
96+
9197
/**
9298
* Instantiates a new Grouped open api.
9399
*
@@ -104,6 +110,7 @@ private GroupedOpenApi(Builder builder) {
104110
this.pathsToExclude = builder.pathsToExclude;
105111
this.openApiCustomisers = Objects.requireNonNull(builder.openApiCustomisers);
106112
this.operationCustomizers = Objects.requireNonNull(builder.operationCustomizers);
113+
this.openApiMethodFilters = Objects.requireNonNull(builder.methodFilters);
107114
if (CollectionUtils.isEmpty(this.pathsToMatch)
108115
&& CollectionUtils.isEmpty(this.packagesToScan)
109116
&& CollectionUtils.isEmpty(this.producesToMatch)
@@ -112,7 +119,8 @@ private GroupedOpenApi(Builder builder) {
112119
&& CollectionUtils.isEmpty(this.pathsToExclude)
113120
&& CollectionUtils.isEmpty(this.packagesToExclude)
114121
&& CollectionUtils.isEmpty(openApiCustomisers)
115-
&& CollectionUtils.isEmpty(operationCustomizers))
122+
&& CollectionUtils.isEmpty(operationCustomizers)
123+
&& CollectionUtils.isEmpty(openApiMethodFilters))
116124
throw new IllegalStateException("Packages to scan or paths to filter or openApiCustomisers/operationCustomizers can not be all null for the group:" + this.group);
117125
}
118126

@@ -215,6 +223,15 @@ public List<OperationCustomizer> getOperationCustomizers() {
215223
return operationCustomizers;
216224
}
217225

226+
/**
227+
* Gets open api method filters.
228+
*
229+
* @return the open api method filters
230+
*/
231+
public List<OpenApiMethodFilter> getOpenApiMethodFilters() {
232+
return openApiMethodFilters;
233+
}
234+
218235
/**
219236
* The type Builder.
220237
* @author bnasslahsen
@@ -230,6 +247,11 @@ public static class Builder {
230247
*/
231248
private final List<OperationCustomizer> operationCustomizers = new ArrayList<>();
232249

250+
/**
251+
* The methods filters to apply.
252+
*/
253+
private final List<OpenApiMethodFilter> methodFilters = new ArrayList<>();
254+
233255
/**
234256
* The Group.
235257
*/
@@ -387,6 +409,17 @@ public Builder addOperationCustomizer(OperationCustomizer operationCustomizer) {
387409
return this;
388410
}
389411

412+
/**
413+
* Add method filter.
414+
*
415+
* @param methodFilter an additional filter to apply to the matched methods
416+
* @return the builder
417+
*/
418+
public Builder addOpenApiMethodFilter(OpenApiMethodFilter methodFilter) {
419+
this.methodFilters.add(methodFilter);
420+
return this;
421+
}
422+
390423
/**
391424
* Build grouped open api.
392425
*
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
*
3+
* *
4+
* * * Copyright 2019-2020 the original author or authors.
5+
* * *
6+
* * * Licensed under the Apache License, Version 2.0 (the "License");
7+
* * * you may not use this file except in compliance with the License.
8+
* * * You may obtain a copy of the License at
9+
* * *
10+
* * * https://www.apache.org/licenses/LICENSE-2.0
11+
* * *
12+
* * * Unless required by applicable law or agreed to in writing, software
13+
* * * distributed under the License is distributed on an "AS IS" BASIS,
14+
* * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* * * See the License for the specific language governing permissions and
16+
* * * limitations under the License.
17+
* *
18+
*
19+
*/
20+
21+
package org.springdoc.core.filters;
22+
23+
import java.lang.reflect.Method;
24+
25+
/**
26+
* A filter to allow conditionally including any detected methods in an OpenApi definition.
27+
* @author michael.clarke
28+
*/
29+
@FunctionalInterface
30+
public interface OpenApiMethodFilter {
31+
32+
/**
33+
* Whether the given method should be included in the generated OpenApi definitions. Only methods from classes
34+
* detected by the relevant loader will be passed to this filter; it cannot be used to load methods that are not
35+
* annotated with `RequestMethod` or similar mechanisms. Methods that are rejected by this filter will not be
36+
* processed any further, although methods accepted by this filter may still be rejected by other checks, such as
37+
* package inclusion checks so may still be excluded from the final OpenApi definition.
38+
*
39+
* @param method the method to perform checks against
40+
* @return whether this method should be used for further processing
41+
*/
42+
boolean isMethodToInclude(Method method);
43+
44+
}

springdoc-openapi-common/src/test/java/org/springdoc/api/AbstractOpenApiResourceTest.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import org.mockito.junit.jupiter.MockitoExtension;
4444
import org.springdoc.core.AbstractRequestService;
4545
import org.springdoc.core.GenericResponseService;
46+
import org.springdoc.core.filters.OpenApiMethodFilter;
4647
import org.springdoc.core.OpenAPIService;
4748
import org.springdoc.core.OperationService;
4849
import org.springdoc.core.SpringDocConfigProperties;
@@ -127,6 +128,7 @@ void calculatePathFromRouterOperation() {
127128
operationParser,
128129
Optional.empty(),
129130
Optional.empty(),
131+
Optional.empty(),
130132
new SpringDocConfigProperties(),
131133
springDocProviders
132134
);
@@ -197,6 +199,7 @@ void preLoadingModeShouldNotOverwriteServers() throws InterruptedException {
197199
operationParser,
198200
Optional.empty(),
199201
Optional.of(singletonList(openApiCustomiser)),
202+
Optional.empty(),
200203
properties, springDocProviders
201204
);
202205

@@ -215,8 +218,8 @@ void preLoadingModeShouldNotOverwriteServers() throws InterruptedException {
215218

216219
private static class EmptyPathsOpenApiResource extends AbstractOpenApiResource {
217220

218-
EmptyPathsOpenApiResource(String groupName, ObjectFactory<OpenAPIService> openAPIBuilderObjectFactory, AbstractRequestService requestBuilder, GenericResponseService responseBuilder, OperationService operationParser, Optional<List<OperationCustomizer>> operationCustomizers, Optional<List<OpenApiCustomiser>> openApiCustomisers, SpringDocConfigProperties springDocConfigProperties, SpringDocProviders springDocProviders) {
219-
super(groupName, openAPIBuilderObjectFactory, requestBuilder, responseBuilder, operationParser, operationCustomizers, openApiCustomisers, springDocConfigProperties, springDocProviders);
221+
EmptyPathsOpenApiResource(String groupName, ObjectFactory<OpenAPIService> openAPIBuilderObjectFactory, AbstractRequestService requestBuilder, GenericResponseService responseBuilder, OperationService operationParser, Optional<List<OperationCustomizer>> operationCustomizers, Optional<List<OpenApiCustomiser>> openApiCustomisers, Optional<List<OpenApiMethodFilter>> methodFilters, SpringDocConfigProperties springDocConfigProperties, SpringDocProviders springDocProviders) {
222+
super(groupName, openAPIBuilderObjectFactory, requestBuilder, responseBuilder, operationParser, operationCustomizers, openApiCustomisers, methodFilters, springDocConfigProperties, springDocProviders);
220223
}
221224

222225
@Override

springdoc-openapi-javadoc/src/test/java/test/org/springdoc/api/app94/SpringDocApp94Test.java

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.apache.commons.lang3.RandomStringUtils;
3030
import org.springdoc.core.AbstractRequestService;
3131
import org.springdoc.core.GenericResponseService;
32+
import org.springdoc.core.filters.OpenApiMethodFilter;
3233
import org.springdoc.core.OpenAPIService;
3334
import org.springdoc.core.OperationService;
3435
import org.springdoc.core.SpringDocConfigProperties;
@@ -117,22 +118,24 @@ public RequestMappingHandlerMapping defaultTestHandlerMapping(GreetingController
117118
/**
118119
* Open api resource open api web mvc resource.
119120
*
120-
* @param openAPIBuilderObjectFactory the open api builder object factory
121-
* @param requestBuilder the request builder
122-
* @param responseBuilder the response builder
123-
* @param operationParser the operation parser
124-
* @param operationCustomizers the operation customizers
121+
* @param openAPIBuilderObjectFactory the open api builder object factory
122+
* @param requestBuilder the request builder
123+
* @param responseBuilder the response builder
124+
* @param operationParser the operation parser
125+
* @param operationCustomizers the operation customizers
125126
* @param springDocConfigProperties the spring doc config properties
126-
* @param openApiCustomisers the open api customisers
127+
* @param openApiCustomisers the open api customisers
128+
* @param methodFilters the method filters
129+
* @param springDocProviders the spring doc providers
127130
* @return the open api web mvc resource
128131
*/
129132
@Bean(name = "openApiResource")
130133
public OpenApiWebMvcResource openApiResource(ObjectFactory<OpenAPIService> openAPIBuilderObjectFactory, AbstractRequestService requestBuilder, GenericResponseService responseBuilder,
131134
OperationService operationParser,Optional<List<OperationCustomizer>> operationCustomizers,
132135
SpringDocConfigProperties springDocConfigProperties,
133-
Optional<List<OpenApiCustomiser>> openApiCustomisers, SpringDocProviders springDocProviders) {
136+
Optional<List<OpenApiCustomiser>> openApiCustomisers, Optional<List<OpenApiMethodFilter>> methodFilters,SpringDocProviders springDocProviders) {
134137
return new OpenApiWebMvcResource(DEFAULT_GROUP_NAME, openAPIBuilderObjectFactory, requestBuilder, responseBuilder, operationParser,
135-
operationCustomizers, openApiCustomisers, springDocConfigProperties, springDocProviders);
138+
operationCustomizers, openApiCustomisers,methodFilters, springDocConfigProperties, springDocProviders);
136139
}
137140

138141
/**

springdoc-openapi-webflux-core/src/main/java/org/springdoc/webflux/api/MultipleOpenApiResource.java

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -132,15 +132,16 @@ public void afterPropertiesSet() {
132132
private OpenApiResource buildWebFluxOpenApiResource(GroupedOpenApi item) {
133133
if (!springDocConfigProperties.isUseManagementPort() && !ACTUATOR_DEFAULT_GROUP.equals(item.getGroup()))
134134
return new OpenApiWebfluxResource(item.getGroup(),
135-
defaultOpenAPIBuilder,
136-
requestBuilder,
137-
responseBuilder,
138-
operationParser,
139-
Optional.of(item.getOperationCustomizers()),
140-
Optional.of(item.getOpenApiCustomisers()),
141-
springDocConfigProperties,
142-
springDocProviders
143-
);
135+
defaultOpenAPIBuilder,
136+
requestBuilder,
137+
responseBuilder,
138+
operationParser,
139+
Optional.of(item.getOperationCustomizers()),
140+
Optional.of(item.getOpenApiCustomisers()),
141+
Optional.of(item.getOpenApiMethodFilters()),
142+
springDocConfigProperties,
143+
springDocProviders
144+
);
144145
else
145146
return new OpenApiActuatorResource(item.getGroup(),
146147
defaultOpenAPIBuilder,
@@ -149,6 +150,7 @@ private OpenApiResource buildWebFluxOpenApiResource(GroupedOpenApi item) {
149150
operationParser,
150151
Optional.of(item.getOperationCustomizers()),
151152
Optional.of(item.getOpenApiCustomisers()),
153+
Optional.of(item.getOpenApiMethodFilters()),
152154
springDocConfigProperties,
153155
springDocProviders);
154156
}

springdoc-openapi-webflux-core/src/main/java/org/springdoc/webflux/api/OpenApiActuatorResource.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import io.swagger.v3.oas.annotations.Operation;
3030
import org.springdoc.core.AbstractRequestService;
3131
import org.springdoc.core.GenericResponseService;
32+
import org.springdoc.core.filters.OpenApiMethodFilter;
3233
import org.springdoc.core.OpenAPIService;
3334
import org.springdoc.core.OperationService;
3435
import org.springdoc.core.SpringDocConfigProperties;
@@ -67,10 +68,12 @@ public class OpenApiActuatorResource extends OpenApiResource {
6768
* @param operationParser the operation parser
6869
* @param operationCustomizers the operation customizers
6970
* @param openApiCustomisers the open api customisers
71+
* @param methodFilters the method filters
7072
* @param springDocConfigProperties the spring doc config properties
73+
* @param springDocProviders the spring doc providers
7174
*/
72-
public OpenApiActuatorResource(String groupName, ObjectFactory<OpenAPIService> openAPIBuilderObjectFactory, AbstractRequestService requestBuilder, GenericResponseService responseBuilder, OperationService operationParser, Optional<List<OperationCustomizer>> operationCustomizers, Optional<List<OpenApiCustomiser>> openApiCustomisers, SpringDocConfigProperties springDocConfigProperties, SpringDocProviders springDocProviders) {
73-
super(groupName, openAPIBuilderObjectFactory, requestBuilder, responseBuilder, operationParser, operationCustomizers, openApiCustomisers, springDocConfigProperties, springDocProviders);
75+
public OpenApiActuatorResource(String groupName, ObjectFactory<OpenAPIService> openAPIBuilderObjectFactory, AbstractRequestService requestBuilder, GenericResponseService responseBuilder, OperationService operationParser, Optional<List<OperationCustomizer>> operationCustomizers, Optional<List<OpenApiCustomiser>> openApiCustomisers, Optional<List<OpenApiMethodFilter>> methodFilters, SpringDocConfigProperties springDocConfigProperties, SpringDocProviders springDocProviders) {
76+
super(groupName, openAPIBuilderObjectFactory, requestBuilder, responseBuilder, operationParser, operationCustomizers, openApiCustomisers, methodFilters, springDocConfigProperties, springDocProviders);
7477
}
7578

7679
/**
@@ -82,10 +85,12 @@ public OpenApiActuatorResource(String groupName, ObjectFactory<OpenAPIService> o
8285
* @param operationParser the operation parser
8386
* @param operationCustomizers the operation customizers
8487
* @param openApiCustomisers the open api customisers
88+
* @param methodFilters the method filters
8589
* @param springDocConfigProperties the spring doc config properties
90+
* @param springDocProviders the spring doc providers
8691
*/
87-
public OpenApiActuatorResource(ObjectFactory<OpenAPIService> openAPIBuilderObjectFactory, AbstractRequestService requestBuilder, GenericResponseService responseBuilder, OperationService operationParser, Optional<List<OperationCustomizer>> operationCustomizers, Optional<List<OpenApiCustomiser>> openApiCustomisers, SpringDocConfigProperties springDocConfigProperties, SpringDocProviders springDocProviders) {
88-
super(openAPIBuilderObjectFactory, requestBuilder, responseBuilder, operationParser, operationCustomizers, openApiCustomisers, springDocConfigProperties, springDocProviders);
92+
public OpenApiActuatorResource(ObjectFactory<OpenAPIService> openAPIBuilderObjectFactory, AbstractRequestService requestBuilder, GenericResponseService responseBuilder, OperationService operationParser, Optional<List<OperationCustomizer>> operationCustomizers, Optional<List<OpenApiCustomiser>> openApiCustomisers, Optional<List<OpenApiMethodFilter>> methodFilters, SpringDocConfigProperties springDocConfigProperties, SpringDocProviders springDocProviders) {
93+
super(openAPIBuilderObjectFactory, requestBuilder, responseBuilder, operationParser, operationCustomizers, openApiCustomisers, methodFilters, springDocConfigProperties, springDocProviders);
8994
}
9095

9196
/**

0 commit comments

Comments
 (0)