Skip to content

Commit 1f2d620

Browse files
committed
Preserve YAML group URLs in Swagger UI
Fixes #3241
1 parent 3e7b337 commit 1f2d620

File tree

3 files changed

+113
-3
lines changed

3 files changed

+113
-3
lines changed

springdoc-openapi-starter-common/src/main/java/org/springdoc/ui/AbstractSwaggerWelcome.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ protected void buildConfigUrl(SwaggerUiConfigParameters swaggerUiConfigParameter
107107
if (StringUtils.isEmpty(swaggerUiConfig.getConfigUrl())) {
108108
buildApiDocUrl(swaggerUiConfigParameters);
109109
buildSwaggerConfigUrl(swaggerUiConfigParameters);
110+
String swaggerUiUrl = swaggerUiConfig.getUrl();
110111
if (CollectionUtils.isEmpty(swaggerUiConfigParameters.getUrls())) {
111-
String swaggerUiUrl = swaggerUiConfig.getUrl();
112112
if (StringUtils.isEmpty(swaggerUiUrl))
113113
swaggerUiConfigParameters.setUrl(swaggerUiConfigParameters.getApiDocsUrl());
114114
else if (swaggerUiConfigParameters.isValidUrl(swaggerUiUrl))
@@ -117,7 +117,7 @@ else if (swaggerUiConfigParameters.isValidUrl(swaggerUiUrl))
117117
swaggerUiConfigParameters.setUrl(buildUrlWithContextPath(swaggerUiConfigParameters, swaggerUiUrl));
118118
}
119119
else
120-
swaggerUiConfigParameters.addUrl(swaggerUiConfigParameters.getApiDocsUrl());
120+
swaggerUiConfigParameters.addUrl(resolveGroupedApiDocsUrl(swaggerUiConfigParameters, swaggerUiUrl));
121121
if (!CollectionUtils.isEmpty(swaggerUiConfig.getUrls())) {
122122
swaggerUiConfig.cloneUrls()
123123
.stream()
@@ -136,6 +136,16 @@ else if (swaggerUiConfigParameters.isValidUrl(swaggerUiUrl))
136136
calculateOauth2RedirectUrl(swaggerUiConfigParameters, uriComponentsBuilder);
137137
}
138138

139+
private String resolveGroupedApiDocsUrl(SwaggerUiConfigParameters swaggerUiConfigParameters, String swaggerUiUrl) {
140+
if (StringUtils.isEmpty(swaggerUiUrl)) {
141+
return swaggerUiConfigParameters.getApiDocsUrl();
142+
}
143+
if (swaggerUiConfigParameters.isValidUrl(swaggerUiUrl)) {
144+
return swaggerUiUrl;
145+
}
146+
return buildUrlWithContextPath(swaggerUiConfigParameters, swaggerUiUrl);
147+
}
148+
139149
/**
140150
* Build swagger ui url string.
141151
*
@@ -237,4 +247,4 @@ protected String getOauth2RedirectUrl() {
237247
protected String getSwaggerUiUrl() {
238248
return SWAGGER_UI_URL;
239249
}
240-
}
250+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
*
3+
* * Copyright 2019-2026 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.ui.app40;
20+
21+
import org.junit.jupiter.api.Test;
22+
import test.org.springdoc.ui.AbstractSpringDocTest;
23+
24+
import org.springframework.test.context.TestPropertySource;
25+
26+
import static org.hamcrest.CoreMatchers.equalTo;
27+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
28+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
29+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
30+
31+
@TestPropertySource(properties = {
32+
"springdoc.swagger-ui.url=/v3/api-docs.yaml",
33+
"springdoc.swagger-ui.urlsPrimaryName=pets"
34+
})
35+
public class SpringDocApp40Test extends AbstractSpringDocTest {
36+
37+
@Test
38+
void swagger_config_preserves_yaml_urls_for_multiple_groups() throws Exception {
39+
mockMvc.perform(get("/v3/api-docs/swagger-config"))
40+
.andExpect(status().isOk())
41+
.andExpect(jsonPath("configUrl", equalTo("/v3/api-docs/swagger-config")))
42+
.andExpect(jsonPath("url", equalTo("/v3/api-docs.yaml")))
43+
.andExpect(jsonPath("urls[0].url", equalTo("/v3/api-docs.yaml/stores")))
44+
.andExpect(jsonPath("urls[0].name", equalTo("stores")))
45+
.andExpect(jsonPath("urls[1].url", equalTo("/v3/api-docs.yaml/pets")))
46+
.andExpect(jsonPath("urls[1].name", equalTo("zpets")))
47+
.andExpect(jsonPath("$['urls.primaryName']", equalTo("pets")));
48+
}
49+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
*
3+
* *
4+
* * *
5+
* * * *
6+
* * * * * Copyright 2019-2026 the original author or authors.
7+
* * * * *
8+
* * * * * Licensed under the Apache License, Version 2.0 (the "License");
9+
* * * * * you may not use this file except in compliance with the License.
10+
* * * * * You may obtain a copy of the License at
11+
* * * * *
12+
* * * * * https://www.apache.org/licenses/LICENSE-2.0
13+
* * * * *
14+
* * * * * Unless required by applicable law or agreed to in writing, software
15+
* * * * * distributed under the License is distributed on an "AS IS" BASIS,
16+
* * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
* * * * * See the License for the specific language governing permissions and
18+
* * * * * limitations under the License.
19+
* * * *
20+
* * *
21+
* *
22+
*
23+
*/
24+
25+
package test.org.springdoc.ui.app40;
26+
27+
import org.springdoc.core.models.GroupedOpenApi;
28+
29+
import org.springframework.boot.autoconfigure.SpringBootApplication;
30+
import org.springframework.context.annotation.Bean;
31+
32+
@SpringBootApplication
33+
public class SpringDocTestApp {
34+
35+
@Bean
36+
public GroupedOpenApi storeOpenApi() {
37+
return GroupedOpenApi.builder()
38+
.group("stores")
39+
.pathsToMatch("/store/**")
40+
.build();
41+
}
42+
43+
@Bean
44+
public GroupedOpenApi groupOpenApi() {
45+
return GroupedOpenApi.builder()
46+
.group("pets")
47+
.displayName("zpets")
48+
.pathsToMatch("/pet/**")
49+
.build();
50+
}
51+
}

0 commit comments

Comments
 (0)