Skip to content

Commit 529fa98

Browse files
author
bnasslahsen
committed
Added support for properties to exclude packages and paths from documentation. Fixes #404
1 parent 9fee50f commit 529fa98

File tree

13 files changed

+261
-48
lines changed

13 files changed

+261
-48
lines changed

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

+23-2
Original file line numberDiff line numberDiff line change
@@ -327,22 +327,43 @@ private PathItem buildPathItem(RequestMethod requestMethod, Operation operation,
327327

328328
protected boolean isPackageToScan(String aPackage) {
329329
List<String> packagesToScan = springDocConfigProperties.getPackagesToScan();
330+
List<String> packagesToExclude = springDocConfigProperties.getPackagesToExclude();
330331
if (CollectionUtils.isEmpty(packagesToScan)) {
331332
Optional<GroupConfig> optionalGroupConfig = springDocConfigProperties.getGroupConfigs().stream().filter(groupConfig -> this.groupName.equals(groupConfig.getGroup())).findAny();
332333
if (optionalGroupConfig.isPresent())
333334
packagesToScan = optionalGroupConfig.get().getPackagesToScan();
334335
}
335-
return CollectionUtils.isEmpty(packagesToScan) || packagesToScan.stream().anyMatch(pack -> aPackage.equals(pack) || aPackage.startsWith(pack + "."));
336+
if (CollectionUtils.isEmpty(packagesToExclude)) {
337+
Optional<GroupConfig> optionalGroupConfig = springDocConfigProperties.getGroupConfigs().stream().filter(groupConfig -> this.groupName.equals(groupConfig.getGroup())).findAny();
338+
if (optionalGroupConfig.isPresent())
339+
packagesToExclude = optionalGroupConfig.get().getPackagesToExclude();
340+
}
341+
boolean include = CollectionUtils.isEmpty(packagesToScan)
342+
|| packagesToScan.stream().anyMatch(pack -> aPackage.equals(pack)
343+
|| aPackage.startsWith(pack + "."));
344+
boolean exclude = !CollectionUtils.isEmpty(packagesToExclude)
345+
&& (packagesToExclude.stream().anyMatch(pack -> aPackage.equals(pack)
346+
|| aPackage.startsWith(pack + ".")));
347+
348+
return include && !exclude;
336349
}
337350

338351
protected boolean isPathToMatch(String operationPath) {
339352
List<String> pathsToMatch = springDocConfigProperties.getPathsToMatch();
353+
List<String> pathsToExclude = springDocConfigProperties.getPathsToExclude();
340354
if (CollectionUtils.isEmpty(pathsToMatch)) {
341355
Optional<GroupConfig> optionalGroupConfig = springDocConfigProperties.getGroupConfigs().stream().filter(groupConfig -> this.groupName.equals(groupConfig.getGroup())).findAny();
342356
if (optionalGroupConfig.isPresent())
343357
pathsToMatch = optionalGroupConfig.get().getPathsToMatch();
344358
}
345-
return CollectionUtils.isEmpty(pathsToMatch) || pathsToMatch.stream().anyMatch(pattern -> antPathMatcher.match(pattern, operationPath));
359+
if (CollectionUtils.isEmpty(pathsToExclude)) {
360+
Optional<GroupConfig> optionalGroupConfig = springDocConfigProperties.getGroupConfigs().stream().filter(groupConfig -> this.groupName.equals(groupConfig.getGroup())).findAny();
361+
if (optionalGroupConfig.isPresent())
362+
pathsToExclude = optionalGroupConfig.get().getPathsToExclude();
363+
}
364+
boolean include = CollectionUtils.isEmpty(pathsToMatch) || pathsToMatch.stream().anyMatch(pattern -> antPathMatcher.match(pattern, operationPath));
365+
boolean exclude = !CollectionUtils.isEmpty(pathsToExclude) && pathsToExclude.stream().anyMatch(pattern -> antPathMatcher.match(pattern, operationPath));
366+
return include && !exclude;
346367
}
347368

348369
protected String decode(String requestURI) {

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

+33-1
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,23 @@ public class GroupedOpenApi {
3737

3838
private final List<String> packagesToScan;
3939

40+
private final List<String> packagesToExclude;
41+
42+
private final List<String> pathsToExclude;
43+
4044
private GroupedOpenApi(Builder builder) {
4145
this.group = Objects.requireNonNull(builder.group, "group");
4246
this.pathsToMatch = builder.pathsToMatch;
4347
this.packagesToScan = builder.packagesToScan;
48+
this.packagesToExclude=builder.packagesToExclude;
49+
this.pathsToExclude=builder.pathsToExclude;
4450
this.openApiCustomisers = Objects.requireNonNull(builder.openApiCustomisers);
4551
SwaggerUiConfigProperties.addGroup(this.group);
46-
if (CollectionUtils.isEmpty(this.pathsToMatch) && CollectionUtils.isEmpty(this.packagesToScan) && CollectionUtils.isEmpty(openApiCustomisers))
52+
if (CollectionUtils.isEmpty(this.pathsToMatch)
53+
&& CollectionUtils.isEmpty(this.packagesToScan)
54+
&& CollectionUtils.isEmpty(this.pathsToExclude)
55+
&& CollectionUtils.isEmpty(this.packagesToExclude)
56+
&& CollectionUtils.isEmpty(openApiCustomisers))
4757
throw new IllegalStateException("Packages to scan or paths to filter or openApiCustomisers can not be all null for the group:" + this.group);
4858
}
4959

@@ -63,6 +73,14 @@ public List<String> getPackagesToScan() {
6373
return packagesToScan;
6474
}
6575

76+
public List<String> getPackagesToExclude() {
77+
return packagesToExclude;
78+
}
79+
80+
public List<String> getPathsToExclude() {
81+
return pathsToExclude;
82+
}
83+
6684
public List<OpenApiCustomiser> getOpenApiCustomisers() {
6785
return openApiCustomisers;
6886
}
@@ -76,6 +94,10 @@ public static class Builder {
7694

7795
private List<String> packagesToScan;
7896

97+
private List<String> packagesToExclude;
98+
99+
private List<String> pathsToExclude;
100+
79101
private Builder() {
80102
// use static factory method in parent class
81103
}
@@ -95,6 +117,16 @@ public Builder packagesToScan(String... packagesToScan) {
95117
return this;
96118
}
97119

120+
public Builder pathsToExclude(String... pathsToExclude) {
121+
this.pathsToExclude = Arrays.asList(pathsToExclude);
122+
return this;
123+
}
124+
125+
public Builder packagesToExclude(String... packagesToExclude) {
126+
this.packagesToExclude = Arrays.asList(packagesToExclude);
127+
return this;
128+
}
129+
98130
public Builder addOpenApiCustomiser(OpenApiCustomiser openApiCustomiser) {
99131
this.openApiCustomisers.add(openApiCustomiser);
100132
return this;

Diff for: springdoc-openapi-common/src/main/java/org/springdoc/core/SpringDocConfigProperties.java

+42-1
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,31 @@ public class SpringDocConfigProperties {
4040

4141
private List<String> packagesToScan;
4242

43+
private List<String> packagesToExclude;
44+
4345
private List<String> pathsToMatch;
4446

47+
private List<String> pathsToExclude;
48+
4549
private Cache cache = new Cache();
4650

4751
private List<GroupConfig> groupConfigs = new ArrayList<>();
4852

53+
public List<String> getPackagesToExclude() {
54+
return packagesToExclude;
55+
}
56+
57+
public void setPackagesToExclude(List<String> packagesToExclude) {
58+
this.packagesToExclude = packagesToExclude;
59+
}
60+
61+
public List<String> getPathsToExclude() {
62+
return pathsToExclude;
63+
}
64+
65+
public void setPathsToExclude(List<String> pathsToExclude) {
66+
this.pathsToExclude = pathsToExclude;
67+
}
4968

5069
public List<String> getPackagesToScan() {
5170
return packagesToScan;
@@ -184,8 +203,10 @@ public void addGroupConfig(GroupConfig groupConfigs) {
184203
public static class GroupConfig {
185204
public GroupConfig() { }
186205

187-
public GroupConfig(String group, List<String> pathsToMatch, List<String> packagesToScan) {
206+
public GroupConfig(String group, List<String> pathsToMatch, List<String> packagesToScan, List<String> packagesToExclude, List<String> pathsToExclude) {
188207
this.pathsToMatch = pathsToMatch;
208+
this.pathsToExclude = pathsToExclude;
209+
this.packagesToExclude = pathsToExclude;
189210
this.packagesToScan = packagesToScan;
190211
this.group = group;
191212
}
@@ -194,6 +215,10 @@ public GroupConfig(String group, List<String> pathsToMatch, List<String> package
194215

195216
private List<String> packagesToScan;
196217

218+
private List<String> packagesToExclude;
219+
220+
private List<String> pathsToExclude;
221+
197222
private String group;
198223

199224
public List<String> getPathsToMatch() {
@@ -219,5 +244,21 @@ public String getGroup() {
219244
public void setGroup(String group) {
220245
this.group = group;
221246
}
247+
248+
public List<String> getPackagesToExclude() {
249+
return packagesToExclude;
250+
}
251+
252+
public void setPackagesToExclude(List<String> packagesToExclude) {
253+
this.packagesToExclude = packagesToExclude;
254+
}
255+
256+
public List<String> getPathsToExclude() {
257+
return pathsToExclude;
258+
}
259+
260+
public void setPathsToExclude(List<String> pathsToExclude) {
261+
this.pathsToExclude = pathsToExclude;
262+
}
222263
}
223264
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ public void afterPropertiesSet() throws Exception {
8888
this.groupedOpenApiResources = groupedOpenApis.stream()
8989
.collect(Collectors.toMap(GroupedOpenApi::getGroup, item ->
9090
{
91-
GroupConfig groupConfig = new GroupConfig(item.getGroup(), item.getPathsToMatch(), item.getPackagesToScan());
91+
GroupConfig groupConfig = new GroupConfig(item.getGroup(), item.getPathsToMatch(), item.getPackagesToScan(), item.getPackagesToExclude(), item.getPathsToExclude());
9292
springDocConfigProperties.addGroupConfig(groupConfig);
9393
return new OpenApiResource(item.getGroup(),
9494
defaultOpenAPIBuilder.getObject(),

Diff for: springdoc-openapi-webmvc-core/src/main/java/org/springdoc/api/MultipleOpenApiResource.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public void afterPropertiesSet() throws Exception {
9191
this.groupedOpenApiResources = groupedOpenApis.stream()
9292
.collect(Collectors.toMap(GroupedOpenApi::getGroup, item ->
9393
{
94-
GroupConfig groupConfig = new GroupConfig(item.getGroup(), item.getPathsToMatch(),item.getPackagesToScan());
94+
GroupConfig groupConfig = new GroupConfig(item.getGroup(), item.getPathsToMatch(), item.getPackagesToScan(), item.getPackagesToExclude(), item.getPathsToExclude());
9595
springDocConfigProperties.addGroupConfig(groupConfig);
9696
return new OpenApiResource(item.getGroup(),
9797
defaultOpenAPIBuilder.getObject(),

Diff for: springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app63/SpringDocApp63Test.java

+2
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,13 @@ public class SpringDocApp63Test extends AbstractSpringDocTest {
2929
@BeforeAll
3030
public static void beforeClass() {
3131
System.setProperty("springdoc.packagesToScan", "hell,hello1, hello.me");
32+
System.setProperty("springdoc.packagesToExclude", "test.org.springdoc.api.app63.65");
3233
}
3334

3435
@AfterAll
3536
public static void afterClass() {
3637
System.clearProperty("springdoc.packagesToScan");
38+
System.clearProperty("springdoc.packagesToExclude");
3739
}
3840

3941
@SpringBootApplication

Diff for: springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/SpringDocTestApp.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public GroupedOpenApi petOpenApi() {
6363
public GroupedOpenApi groupOpenApi() {
6464
return GroupedOpenApi.builder()
6565
.setGroup("groups test")
66-
.pathsToMatch("/v1/**")
66+
.pathsToMatch("/v1/**").pathsToExclude("/v1/users")
6767
.packagesToScan("test.org.springdoc.api.app68.api.user", "test.org.springdoc.api.app68.api.store")
6868
.build();
6969
}

Diff for: springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app85/HelloController.java

-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import io.swagger.v3.oas.annotations.Operation;
2222
import io.swagger.v3.oas.annotations.Parameter;
2323

24-
import org.springframework.web.bind.annotation.GetMapping;
2524
import org.springframework.web.bind.annotation.PathVariable;
2625
import org.springframework.web.bind.annotation.PostMapping;
2726
import org.springframework.web.bind.annotation.RequestMapping;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
*
3+
* * Copyright 2019-2020 the original author or authors.
4+
* *
5+
* * Licensed under the Apache License, Version 2.0 (the "License");
6+
* * you may not use this file except in compliance with the License.
7+
* * You may obtain a copy of the License at
8+
* *
9+
* * https://www.apache.org/licenses/LICENSE-2.0
10+
* *
11+
* * Unless required by applicable law or agreed to in writing, software
12+
* * distributed under the License is distributed on an "AS IS" BASIS,
13+
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* * See the License for the specific language governing permissions and
15+
* * limitations under the License.
16+
*
17+
*/
18+
19+
package test.org.springdoc.api.app86;
20+
21+
import java.util.Locale;
22+
23+
import javax.servlet.http.HttpServletRequest;
24+
import javax.servlet.http.HttpServletResponse;
25+
import javax.servlet.http.HttpSession;
26+
27+
import org.springframework.web.bind.annotation.GetMapping;
28+
import org.springframework.web.bind.annotation.RestController;
29+
30+
@RestController
31+
public class HelloController {
32+
33+
@GetMapping("/test")
34+
public void test(HttpSession header, HttpServletRequest request, HttpServletResponse response, Locale locale,
35+
String hello) {
36+
}
37+
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
*
3+
* * Copyright 2019-2020 the original author or authors.
4+
* *
5+
* * Licensed under the Apache License, Version 2.0 (the "License");
6+
* * you may not use this file except in compliance with the License.
7+
* * You may obtain a copy of the License at
8+
* *
9+
* * https://www.apache.org/licenses/LICENSE-2.0
10+
* *
11+
* * Unless required by applicable law or agreed to in writing, software
12+
* * distributed under the License is distributed on an "AS IS" BASIS,
13+
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* * See the License for the specific language governing permissions and
15+
* * limitations under the License.
16+
*
17+
*/
18+
19+
package test.org.springdoc.api.app86;
20+
21+
import org.junit.jupiter.api.AfterAll;
22+
import org.junit.jupiter.api.BeforeAll;
23+
import test.org.springdoc.api.AbstractSpringDocTest;
24+
25+
import org.springframework.boot.autoconfigure.SpringBootApplication;
26+
27+
public class SpringDocApp86Test extends AbstractSpringDocTest {
28+
29+
@BeforeAll
30+
public static void beforeClass() {
31+
System.setProperty("springdoc.packagesToScan", "test.org.springdoc.api.app86");
32+
System.setProperty("springdoc.packagesToExclude", "test.org.springdoc.api.app86.test");
33+
}
34+
35+
@AfterAll
36+
public static void afterClass() {
37+
System.clearProperty("springdoc.packagesToScan");
38+
System.clearProperty("springdoc.packagesToExclude");
39+
}
40+
41+
@SpringBootApplication
42+
static class SpringDocTestApp {}
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
*
3+
* * Copyright 2019-2020 the original author or authors.
4+
* *
5+
* * Licensed under the Apache License, Version 2.0 (the "License");
6+
* * you may not use this file except in compliance with the License.
7+
* * You may obtain a copy of the License at
8+
* *
9+
* * https://www.apache.org/licenses/LICENSE-2.0
10+
* *
11+
* * Unless required by applicable law or agreed to in writing, software
12+
* * distributed under the License is distributed on an "AS IS" BASIS,
13+
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* * See the License for the specific language governing permissions and
15+
* * limitations under the License.
16+
*
17+
*/
18+
19+
package test.org.springdoc.api.app86.test;
20+
21+
import java.util.Locale;
22+
23+
import javax.servlet.http.HttpServletRequest;
24+
import javax.servlet.http.HttpServletResponse;
25+
import javax.servlet.http.HttpSession;
26+
27+
import org.springframework.web.bind.annotation.GetMapping;
28+
import org.springframework.web.bind.annotation.RestController;
29+
30+
@RestController
31+
public class HelloController2 {
32+
33+
@GetMapping("/test2")
34+
public void test(HttpSession header, HttpServletRequest request, HttpServletResponse response, Locale locale,
35+
String hello) {
36+
}
37+
38+
}

0 commit comments

Comments
 (0)