Skip to content

Commit 59320da

Browse files
committed
improved version
1 parent 5817e80 commit 59320da

File tree

15 files changed

+487
-73
lines changed

15 files changed

+487
-73
lines changed

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,19 @@ public final class Constants {
9595
*/
9696
public static final String SPRINGDOC_SWAGGER_UI_ENABLED = "springdoc.swagger-ui.enabled";
9797

98+
99+
/**
100+
* The constant SPRINGDOC_USE_MANAGEMENT_PORT.
101+
*/
102+
public static final String SPRINGDOC_USE_MANAGEMENT_PORT = "springdoc.use-management-port";
103+
104+
/**
105+
* The constant DEFAULT_SWAGGER_UI_ACTUATOR_PATH.
106+
*/
107+
public static final String DEFAULT_SWAGGER_UI_ACTUATOR_PATH= "swagger-ui";
108+
109+
public static final String DEFAULT_API_DOCS_ACTUATOR_URL = "openapi";
110+
98111
/**
99112
* The constant NULL.
100113
*/

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,28 @@ public class SpringDocConfigProperties {
157157
*/
158158
private boolean preLoadingEnabled;
159159

160+
/**
161+
* If set to true, exposes the swagger-ui on the actuator management port.
162+
*/
163+
private boolean useManagementPort;
164+
165+
/**
166+
* Is use management port boolean.
167+
*
168+
* @return the boolean
169+
*/
170+
public boolean isUseManagementPort() {
171+
return useManagementPort;
172+
}
173+
174+
/**
175+
* Sets use management port.
176+
*
177+
* @param useManagementPort the use management port
178+
*/
179+
public void setUseManagementPort(boolean useManagementPort) {
180+
this.useManagementPort = useManagementPort;
181+
}
160182

161183
/**
162184
* Gets produces to match.

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

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,10 @@
2727

2828
import com.fasterxml.jackson.databind.node.ObjectNode;
2929
import io.swagger.v3.core.converter.ModelConverter;
30-
import io.swagger.v3.oas.annotations.Hidden;
3130
import io.swagger.v3.oas.models.Components;
3231
import io.swagger.v3.oas.models.OpenAPI;
3332
import io.swagger.v3.oas.models.media.ObjectSchema;
3433
import io.swagger.v3.oas.models.media.Schema;
35-
import org.springdoc.api.ErrorMessage;
36-
import org.springdoc.api.OpenApiResourceNotFoundException;
3734
import org.springdoc.core.converters.AdditionalModelsConverter;
3835
import org.springdoc.core.converters.FileSupportConverter;
3936
import org.springdoc.core.converters.ModelConverterRegistrar;
@@ -59,12 +56,6 @@
5956
import org.springframework.context.annotation.Configuration;
6057
import org.springframework.context.annotation.Lazy;
6158
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
62-
import org.springframework.http.HttpStatus;
63-
import org.springframework.http.ResponseEntity;
64-
import org.springframework.web.bind.annotation.ExceptionHandler;
65-
import org.springframework.web.bind.annotation.ResponseStatus;
66-
import org.springframework.web.bind.annotation.RestControllerAdvice;
67-
import org.springframework.web.context.request.WebRequest;
6859
import org.springframework.web.context.request.async.DeferredResult;
6960

7061
import static org.springdoc.core.Constants.SPRINGDOC_DEPRECATING_CONVERTER_ENABLED;
@@ -318,7 +309,7 @@ static BeanFactoryPostProcessor springdocBeanFactoryPostProcessor() {
318309
*
319310
* @return the bean factory post processor
320311
*/
321-
// For spring-boot-1 compatibility
312+
// For spring-boot-1 compatibility
322313
@Bean
323314
@Conditional(CacheOrGroupedOpenApiCondition.class)
324315
@ConditionalOnMissingClass(value = BINDRESULT_CLASS)
@@ -327,24 +318,4 @@ static BeanFactoryPostProcessor springdocBeanFactoryPostProcessor2() {
327318
return SpringdocBeanFactoryConfigurer::initBeanFactoryPostProcessor;
328319
}
329320

330-
/**
331-
* The type Open api resource advice.
332-
*/
333-
@RestControllerAdvice
334-
@Hidden
335-
class OpenApiResourceAdvice {
336-
/**
337-
* Handle no handler found response entity.
338-
*
339-
* @param e the e
340-
* @param request the request
341-
* @return the response entity
342-
*/
343-
@ExceptionHandler(OpenApiResourceNotFoundException.class)
344-
@ResponseStatus(HttpStatus.NOT_FOUND)
345-
public ResponseEntity<ErrorMessage> handleNoHandlerFound(OpenApiResourceNotFoundException e, WebRequest request) {
346-
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorMessage(e.getMessage()));
347-
}
348-
}
349-
350321
}

springdoc-openapi-ui/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,11 @@
3232
<artifactId>spring-boot-starter-security</artifactId>
3333
<scope>test</scope>
3434
</dependency>
35+
<!-- Actuator dependencies -->
36+
<dependency>
37+
<groupId>org.springframework.boot</groupId>
38+
<artifactId>spring-boot-starter-actuator</artifactId>
39+
<optional>true</optional>
40+
</dependency>
3541
</dependencies>
3642
</project>
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package org.springdoc.webmvc.ui;
2+
3+
import java.util.Map;
4+
5+
import javax.servlet.http.HttpServletRequest;
6+
7+
import io.swagger.v3.oas.annotations.Operation;
8+
import org.apache.commons.lang3.StringUtils;
9+
import org.springdoc.core.SpringDocConfigProperties;
10+
import org.springdoc.core.SwaggerUiConfigParameters;
11+
import org.springdoc.core.SwaggerUiConfigProperties;
12+
13+
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
14+
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpoint;
15+
import org.springframework.http.MediaType;
16+
import org.springframework.util.CollectionUtils;
17+
import org.springframework.web.bind.annotation.GetMapping;
18+
import org.springframework.web.bind.annotation.ResponseBody;
19+
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
20+
import org.springframework.web.servlet.view.UrlBasedViewResolver;
21+
import org.springframework.web.util.UriComponentsBuilder;
22+
23+
import static org.springdoc.core.Constants.DEFAULT_API_DOCS_ACTUATOR_URL;
24+
import static org.springdoc.core.Constants.DEFAULT_SWAGGER_UI_ACTUATOR_PATH;
25+
import static org.springdoc.core.Constants.SWAGGER_UI_URL;
26+
import static org.springdoc.core.Constants.SWAGGGER_CONFIG_FILE;
27+
import static org.springframework.util.AntPathMatcher.DEFAULT_PATH_SEPARATOR;
28+
29+
/**
30+
* The type Swagger actuator welcome.
31+
*/
32+
@ControllerEndpoint(id = DEFAULT_SWAGGER_UI_ACTUATOR_PATH)
33+
public class SwaggerActuatorWelcome extends SwaggerWelcome {
34+
35+
/**
36+
* The Web endpoint properties.
37+
*/
38+
private WebEndpointProperties webEndpointProperties;
39+
40+
public static final String SWAGGER_CONFIG_ACTUATOR_URL = DEFAULT_PATH_SEPARATOR + SWAGGGER_CONFIG_FILE;
41+
42+
43+
/**
44+
* Instantiates a new Swagger welcome.
45+
* @param swaggerUiConfig the swagger ui config
46+
* @param springDocConfigProperties the spring doc config properties
47+
* @param swaggerUiConfigParameters the swagger ui config parameters
48+
* @param webEndpointProperties the web endpoint properties
49+
*/
50+
public SwaggerActuatorWelcome(SwaggerUiConfigProperties swaggerUiConfig, SpringDocConfigProperties springDocConfigProperties, SwaggerUiConfigParameters swaggerUiConfigParameters, WebEndpointProperties webEndpointProperties) {
51+
super(swaggerUiConfig, springDocConfigProperties, swaggerUiConfigParameters);
52+
this.webEndpointProperties = webEndpointProperties;
53+
}
54+
55+
/**
56+
* Redirect to ui string.
57+
*
58+
* @param request the request
59+
* @return the string
60+
*/
61+
@Operation(hidden = true)
62+
@GetMapping("/")
63+
public String redirectToUi(HttpServletRequest request) {
64+
buildConfigUrl(request.getContextPath(), ServletUriComponentsBuilder.fromCurrentContextPath());
65+
String sbUrl = swaggerUiConfigParameters.getUiRootPath() + SWAGGER_UI_URL;
66+
UriComponentsBuilder uriBuilder = getUriComponentsBuilder(sbUrl);
67+
return UrlBasedViewResolver.REDIRECT_URL_PREFIX + uriBuilder.build().encode().toString();
68+
}
69+
70+
/**
71+
* Openapi yaml map.
72+
*
73+
* @param request the request
74+
* @return the map
75+
*/
76+
@Operation(hidden = true)
77+
@GetMapping(value = SWAGGER_CONFIG_ACTUATOR_URL, produces = MediaType.APPLICATION_JSON_VALUE)
78+
@ResponseBody
79+
public Map<String, Object> openapiJson(HttpServletRequest request) {
80+
buildConfigUrl(request.getContextPath(), ServletUriComponentsBuilder.fromCurrentContextPath());
81+
return swaggerUiConfigParameters.getConfigParameters();
82+
}
83+
84+
85+
protected void buildConfigUrl(String contextPath, UriComponentsBuilder uriComponentsBuilder) {
86+
String apiDocsUrl = DEFAULT_API_DOCS_ACTUATOR_URL;
87+
if (StringUtils.isEmpty(swaggerUiConfig.getConfigUrl())) {
88+
String url = webEndpointProperties.getBasePath() + DEFAULT_PATH_SEPARATOR + buildUrl(contextPath, apiDocsUrl);
89+
String swaggerConfigUrl = webEndpointProperties.getBasePath()
90+
+ DEFAULT_PATH_SEPARATOR + DEFAULT_SWAGGER_UI_ACTUATOR_PATH
91+
+ DEFAULT_PATH_SEPARATOR + SWAGGGER_CONFIG_FILE;
92+
swaggerUiConfigParameters.setConfigUrl(swaggerConfigUrl);
93+
if (CollectionUtils.isEmpty(swaggerUiConfigParameters.getUrls())) {
94+
String swaggerUiUrl = swaggerUiConfig.getUrl();
95+
if (StringUtils.isEmpty(swaggerUiUrl))
96+
swaggerUiConfigParameters.setUrl(url);
97+
else
98+
swaggerUiConfigParameters.setUrl(swaggerUiUrl);
99+
}
100+
else
101+
swaggerUiConfigParameters.addUrl(url);
102+
}
103+
calculateOauth2RedirectUrl(uriComponentsBuilder);
104+
}
105+
106+
}

springdoc-openapi-ui/src/main/java/org/springdoc/webmvc/ui/SwaggerConfig.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.springdoc.core.SwaggerUiConfigProperties;
2828
import org.springdoc.core.SwaggerUiOAuthProperties;
2929

30+
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
3031
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
3132
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
3233
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -35,6 +36,7 @@
3536
import org.springframework.context.annotation.Lazy;
3637

3738
import static org.springdoc.core.Constants.SPRINGDOC_SWAGGER_UI_ENABLED;
39+
import static org.springdoc.core.Constants.SPRINGDOC_USE_MANAGEMENT_PORT;
3840

3941

4042
/**
@@ -57,10 +59,18 @@ public class SwaggerConfig {
5759
*/
5860
@Bean
5961
@ConditionalOnMissingBean
62+
@ConditionalOnProperty(name = SPRINGDOC_USE_MANAGEMENT_PORT, havingValue = "false", matchIfMissing = true)
6063
SwaggerWelcome swaggerWelcome(SwaggerUiConfigProperties swaggerUiConfig, SpringDocConfigProperties springDocConfigProperties, SwaggerUiConfigParameters swaggerUiConfigParameters) {
6164
return new SwaggerWelcome(swaggerUiConfig, springDocConfigProperties,swaggerUiConfigParameters);
6265
}
6366

67+
@Bean
68+
@ConditionalOnMissingBean
69+
@ConditionalOnProperty(SPRINGDOC_USE_MANAGEMENT_PORT)
70+
SwaggerActuatorWelcome swaggerActuatorWelcome(SwaggerUiConfigProperties swaggerUiConfig, SpringDocConfigProperties springDocConfigProperties, SwaggerUiConfigParameters swaggerUiConfigParameters, WebEndpointProperties webEndpointProperties) {
71+
return new SwaggerActuatorWelcome(swaggerUiConfig, springDocConfigProperties,swaggerUiConfigParameters,webEndpointProperties);
72+
}
73+
6474
/**
6575
* Index page transformer swagger index transformer.
6676
*

springdoc-openapi-ui/src/main/java/org/springdoc/webmvc/ui/SwaggerWelcome.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,11 @@
2828
import org.apache.commons.lang3.ArrayUtils;
2929
import org.apache.commons.lang3.StringUtils;
3030
import org.springdoc.core.SpringDocConfigProperties;
31-
import org.springdoc.core.SpringDocConfiguration;
3231
import org.springdoc.core.SwaggerUiConfigParameters;
3332
import org.springdoc.core.SwaggerUiConfigProperties;
3433
import org.springdoc.ui.AbstractSwaggerWelcome;
3534

3635
import org.springframework.beans.factory.annotation.Value;
37-
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
38-
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
3936
import org.springframework.http.MediaType;
4037
import org.springframework.stereotype.Controller;
4138
import org.springframework.web.bind.annotation.GetMapping;
@@ -45,7 +42,6 @@
4542
import org.springframework.web.util.UriComponentsBuilder;
4643

4744
import static org.springdoc.core.Constants.MVC_SERVLET_PATH;
48-
import static org.springdoc.core.Constants.SPRINGDOC_SWAGGER_UI_ENABLED;
4945
import static org.springdoc.core.Constants.SWAGGER_CONFIG_URL;
5046
import static org.springdoc.core.Constants.SWAGGER_UI_PATH;
5147
import static org.springdoc.core.Constants.SWAGGER_UI_URL;
@@ -56,8 +52,6 @@
5652
* @author bnasslahsen
5753
*/
5854
@Controller
59-
@ConditionalOnProperty(name = SPRINGDOC_SWAGGER_UI_ENABLED, matchIfMissing = true)
60-
@ConditionalOnBean(SpringDocConfiguration.class)
6155
public class SwaggerWelcome extends AbstractSwaggerWelcome {
6256

6357
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package org.springdoc.webmvc.api;
2+
3+
import java.util.List;
4+
import java.util.Optional;
5+
6+
import javax.servlet.http.HttpServletRequest;
7+
8+
import com.fasterxml.jackson.core.JsonProcessingException;
9+
import io.swagger.v3.oas.annotations.Operation;
10+
import org.springdoc.core.AbstractRequestService;
11+
import org.springdoc.core.ActuatorProvider;
12+
import org.springdoc.core.GenericResponseService;
13+
import org.springdoc.core.GroupedOpenApi;
14+
import org.springdoc.core.OpenAPIService;
15+
import org.springdoc.core.OperationService;
16+
import org.springdoc.core.RepositoryRestResourceProvider;
17+
import org.springdoc.core.SecurityOAuth2Provider;
18+
import org.springdoc.core.SpringDocConfigProperties;
19+
20+
import org.springframework.beans.factory.ObjectFactory;
21+
import org.springframework.boot.actuate.endpoint.web.annotation.RestControllerEndpoint;
22+
import org.springframework.http.MediaType;
23+
import org.springframework.web.bind.annotation.GetMapping;
24+
import org.springframework.web.bind.annotation.PathVariable;
25+
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
26+
27+
import static org.springdoc.core.Constants.APPLICATION_OPENAPI_YAML;
28+
import static org.springdoc.core.Constants.DEFAULT_API_DOCS_ACTUATOR_URL;
29+
import static org.springframework.util.AntPathMatcher.DEFAULT_PATH_SEPARATOR;
30+
31+
@RestControllerEndpoint(id = DEFAULT_API_DOCS_ACTUATOR_URL)
32+
public class MultipleOpenApiActuatorResource extends MultipleOpenApiResource {
33+
34+
/**
35+
* Instantiates a new Multiple open api resource.
36+
* @param groupedOpenApis the grouped open apis
37+
* @param defaultOpenAPIBuilder the default open api builder
38+
* @param requestBuilder the request builder
39+
* @param responseBuilder the response builder
40+
* @param operationParser the operation parser
41+
* @param requestMappingHandlerMapping the request mapping handler mapping
42+
* @param actuatorProvider the actuator provider
43+
* @param springDocConfigProperties the spring doc config properties
44+
* @param springSecurityOAuth2Provider the spring security o auth 2 provider
45+
* @param routerFunctionProvider the router function provider
46+
* @param repositoryRestResourceProvider the repository rest resource provider
47+
*/
48+
public MultipleOpenApiActuatorResource(List<GroupedOpenApi> groupedOpenApis,
49+
ObjectFactory<OpenAPIService> defaultOpenAPIBuilder, AbstractRequestService requestBuilder,
50+
GenericResponseService responseBuilder, OperationService operationParser,
51+
RequestMappingInfoHandlerMapping requestMappingHandlerMapping, Optional<ActuatorProvider> actuatorProvider,
52+
SpringDocConfigProperties springDocConfigProperties, Optional<SecurityOAuth2Provider> springSecurityOAuth2Provider,
53+
Optional<RouterFunctionProvider> routerFunctionProvider, Optional<RepositoryRestResourceProvider> repositoryRestResourceProvider) {
54+
super(groupedOpenApis, defaultOpenAPIBuilder, requestBuilder, responseBuilder, operationParser, requestMappingHandlerMapping, actuatorProvider, springDocConfigProperties, springSecurityOAuth2Provider, routerFunctionProvider, repositoryRestResourceProvider);
55+
}
56+
57+
58+
/**
59+
* Openapi json string.
60+
*
61+
* @param request the request
62+
* @param group the group
63+
* @return the string
64+
* @throws JsonProcessingException the json processing exception
65+
*/
66+
@Operation(hidden = true)
67+
@GetMapping(value = "/{group}", produces = MediaType.APPLICATION_JSON_VALUE)
68+
public String openapiJson(HttpServletRequest request,
69+
@PathVariable String group)
70+
throws JsonProcessingException {
71+
return getOpenApiResourceOrThrow(group).openapiJson(request, "" + DEFAULT_PATH_SEPARATOR + group);
72+
}
73+
74+
/**
75+
* Openapi yaml string.
76+
*
77+
* @param request the request
78+
* @param group the group
79+
* @return the string
80+
* @throws JsonProcessingException the json processing exception
81+
*/
82+
@Operation(hidden = true)
83+
@GetMapping(value = "/{group}/yaml", produces = APPLICATION_OPENAPI_YAML)
84+
public String openapiYaml(HttpServletRequest request,
85+
@PathVariable String group)
86+
throws JsonProcessingException {
87+
return getOpenApiResourceOrThrow(group).openapiYaml(request, "" + DEFAULT_PATH_SEPARATOR + group);
88+
}
89+
90+
}

0 commit comments

Comments
 (0)