Repository: springdoc/springdoc-openapi
Pull request #919 (2020-10-31 14:35:04)

Fix issue #907
fix issue 907


Patch:
diff --git a/springdoc-openapi-common/src/main/java/org/springdoc/core/OpenAPIService.java b/springdoc-openapi-common/src/main/java/org/springdoc/core/OpenAPIService.java
index 504f4d3e0..91bf43f26 100644
--- a/springdoc-openapi-common/src/main/java/org/springdoc/core/OpenAPIService.java
+++ b/springdoc-openapi-common/src/main/java/org/springdoc/core/OpenAPIService.java
@@ -58,6 +58,7 @@ import org.springdoc.core.customizers.OpenApiBuilderCustomizer;
 
 import org.springframework.beans.factory.config.BeanDefinition;
 import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
+import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
 import org.springframework.core.annotation.AnnotatedElementUtils;
@@ -73,6 +74,7 @@ import org.springframework.web.method.HandlerMethod;
 import static org.springdoc.core.Constants.DEFAULT_SERVER_DESCRIPTION;
 import static org.springdoc.core.Constants.DEFAULT_TITLE;
 import static org.springdoc.core.Constants.DEFAULT_VERSION;
+import static org.springdoc.core.SpringDocUtils.getConfig;
 
 /**
  * The type Open api builder.
@@ -213,11 +215,23 @@ public class OpenAPIService {
 		this.mappingsMap.putAll(context.getBeansWithAnnotation(RequestMapping.class));
 		this.mappingsMap.putAll(context.getBeansWithAnnotation(Controller.class));
 
+		initializeHiddenRestController();
+
 		// add security schemes
 		this.calculateSecuritySchemes(calculatedOpenAPI.getComponents());
 		openApiBuilderCustomisers.ifPresent(customisers -> customisers.forEach(customiser -> customiser.customise(this)));
 	}
 
+	private void initializeHiddenRestController() {
+		getConfig().addHiddenRestControllers(BasicErrorController.class);
+		List<Class<?>> hiddenRestControllers = this.mappingsMap.entrySet().parallelStream()
+				.filter(controller -> (AnnotationUtils.findAnnotation(controller.getValue().getClass(),
+						Hidden.class) != null)).map(controller -> controller.getValue().getClass())
+				.collect(Collectors.toList());
+		if(!CollectionUtils.isEmpty(hiddenRestControllers))
+			getConfig().addHiddenRestControllers(hiddenRestControllers.toArray(new Class<?>[hiddenRestControllers.size()]));
+	}
+
 	/**
 	 * Update servers open api.
 	 *


Test patch:
diff --git a/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app143/HelloHiddenController.java b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app143/HelloHiddenController.java
new file mode 100644
index 000000000..76c59eb64
--- /dev/null
+++ b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app143/HelloHiddenController.java
@@ -0,0 +1,37 @@
+/*
+ *
+ *  * Copyright 2019-2020 the original author or authors.
+ *  *
+ *  * Licensed under the Apache License, Version 2.0 (the "License");
+ *  * you may not use this file except in compliance with the License.
+ *  * You may obtain a copy of the License at
+ *  *
+ *  *      https://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+
+package test.org.springdoc.api.app143;
+
+import io.swagger.v3.oas.annotations.Hidden;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@Hidden
+public class HelloHiddenController {
+
+	@GetMapping("/testA")
+	public void testA(String hello) {
+	}
+
+	@GetMapping("/testB")
+	public void testB(String hello) {
+	}
+}
diff --git a/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app143/SpringDocApp143Test.java b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app143/SpringDocApp143Test.java
new file mode 100644
index 000000000..4cca79ecb
--- /dev/null
+++ b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app143/SpringDocApp143Test.java
@@ -0,0 +1,59 @@
+/*
+ *
+ *  * Copyright 2019-2020 the original author or authors.
+ *  *
+ *  * Licensed under the Apache License, Version 2.0 (the "License");
+ *  * you may not use this file except in compliance with the License.
+ *  * You may obtain a copy of the License at
+ *  *
+ *  *      https://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+
+package test.org.springdoc.api.app143;
+
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springdoc.core.Constants;
+import test.org.springdoc.api.AbstractSpringDocTest;
+
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.is;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+/**
+ * Test issue 907 fix.
+ * Hidden controller showing up in swagger UI when springdoc.show-actuator is enabled
+ */
+@TestPropertySource(properties = "springdoc.show-actuator=true")
+public class SpringDocApp143Test extends AbstractSpringDocTest {
+
+	@SpringBootApplication
+	static class SpringDocTestApp {}
+
+	@Test
+	public void testApp() throws Exception {
+		MvcResult mockMvcResult = mockMvc.perform(MockMvcRequestBuilders.get(Constants.DEFAULT_API_DOCS_URL)).andExpect(status().isOk())
+				.andExpect(jsonPath("$.openapi", is("3.0.1")))
+				.andExpect(jsonPath("$.paths./actuator/info.get.operationId", containsString("handle_")))
+				.andExpect(jsonPath("$.paths./actuator/info.get.summary", Matchers.is("Actuator web endpoint 'info'")))
+				.andExpect(jsonPath("$.paths./actuator/health.get.operationId", containsString("handle_")))
+				.andReturn();
+		String result = mockMvcResult.getResponse().getContentAsString();
+		String expected = getContent("results/app143.json");
+		Assertions.assertEquals(expected, result);
+	}
+}
diff --git a/springdoc-openapi-webmvc-core/src/test/resources/results/app143.json b/springdoc-openapi-webmvc-core/src/test/resources/results/app143.json
new file mode 100644
index 000000000..b226ad339
--- /dev/null
+++ b/springdoc-openapi-webmvc-core/src/test/resources/results/app143.json
@@ -0,0 +1,1 @@
+{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"http://localhost","description":"Generated server url"}],"tags":[{"name":"Actuator","description":"Monitor and interact","externalDocs":{"description":"Spring Boot Actuator Web API Documentation","url":"https://docs.spring.io/spring-boot/docs/current/actuator-api/html/"}}],"paths":{"/actuator":{"get":{"tags":["Actuator"],"summary":"Actuator root web endpoint","operationId":"links_0","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/Link"}}}}}}}}},"/actuator/health":{"get":{"tags":["Actuator"],"summary":"Actuator web endpoint 'health'","operationId":"handle_2","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/actuator/health/**":{"get":{"tags":["Actuator"],"summary":"Actuator web endpoint 'health-path'","operationId":"handle_3","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/actuator/info":{"get":{"tags":["Actuator"],"summary":"Actuator web endpoint 'info'","operationId":"handle_1","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object"}}}}}}}},"components":{"schemas":{"Link":{"type":"object","properties":{"href":{"type":"string"},"templated":{"type":"boolean"}}}}}}
\ No newline at end of file