Spring Boot 3에서 SpringDoc 사용시 PetStore API가 노출되는 문제

SpringDoc 최근 버전에서 발생하는 문제로 Configuration을 변경하더라도 SpringDoc Swagger UI에 접근시 PetStore API가 노출되는 문제가 있음.

이 문제를 해결하는데 1주일 이상 걸렸음. Transformer 기능이 있다는 것 확인함.

POM

  • openapi.version - 2.6.0
 <dependency>
	<groupId>org.springdoc</groupId>
	<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
	<version>${openapi.version}</version>
</dependency>

<dependency>
	<groupId>org.springdoc</groupId>
	<artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
	<version>${openapi.version}</version>
</dependency>

YAML

springdoc:
  version: '@project.version@'
  api-docs:
    path: /api/v1/api-docs
  default-consumes-media-type: application/json
  default-produces-media-type: application/json
  swagger-ui:
    operations-sorter: alpha
    tags-sorter: alpha
    path: /swagger-ui.html
    disable-swagger-default-url: true
    display-query-params-without-oauth2: true
  paths-to-match:
    - /api/v1/**

WebMvcConfigurer

import io.micrometer.core.instrument.util.IOUtils;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.info.Info;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.resource.PathResourceResolver;
import org.springframework.web.servlet.resource.ResourceTransformer;
import org.springframework.web.servlet.resource.ResourceTransformerChain;
import org.springframework.web.servlet.resource.TransformedResource;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

@OpenAPIDefinition(
        info = @Info(
                title = "Messaging API",
                version = "1.0.0",
                description = "Messaging API"
        )
)
@Configuration
public class WebAppConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/swagger-ui/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/swagger-ui/5.17.14/")
                .resourceChain(false)
                .addResolver(new PathResourceResolver())
                .addTransformer(new IndexPageTransformer()); // TRANSFORMER
    }

    public static class IndexPageTransformer implements ResourceTransformer {

        private String overwriteDefaultUrl(String html) {
            return html.replace("https://petstore.swagger.io/v2/swagger.json", "/api/v1/api-docs"); // API URI 수정
        }

        @Override
        public Resource transform(HttpServletRequest httpServletRequest, Resource resource, ResourceTransformerChain resourceTransformerChain) throws IOException {
            if (resource.getURL().toString().endsWith("/swagger-ui/index.html")) {
                String html = IOUtils.toString(resource.getInputStream(), StandardCharsets.UTF_8);
                html = overwriteDefaultUrl(html);
                return new TransformedResource(resource, html.getBytes());
            } else {
                return resource;
            }
        }
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        // /로 접속하면 Swagger Open API 페이지가 표시되도록 리다이렉트 규칙 추가
        registry.addRedirectViewController("/", "/swagger-ui/index.html");
    }

}