gengminy
갱미니의 코딩일지
gengminy
전체 방문자
오늘
어제
  • 분류 전체보기 (61)
    • 🚀 프로젝트 (16)
      • 🎸 고스락 티켓 (4)
      • 🌞 내친소 (5)
      • 🥁 두둥 (7)
    • 📡 백엔드 (31)
      • 🌱 Spring Boot (13)
      • 🐱 Nest.js (10)
      • ⭐ Node.js (8)
    • 🏭 Infra (11)
      • ⚙ 준비를 위한 준비 (2)
      • 🥑 AWS (3)
      • 🐳 Docker (3)
      • ⚡ Github Actions (3)
    • 🌊 프론트엔드 (1)
      • 🌌 React.js (1)
    • 😎 주저리 (2)

블로그 메뉴

  • 💻Github
  • 📸Instagram
  • ✨Blog

공지사항

인기 글

태그

  • OAuth
  • AWS
  • nestjs
  • GithubActions
  • 스프링부트
  • JSON
  • 네스트
  • springboot
  • Spring
  • 스프링
  • JWT
  • 슬랙알림
  • github
  • nodejs
  • oauth2
  • docker
  • 도커
  • SlackAPI
  • 깃헙액션
  • nest

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
gengminy

갱미니의 코딩일지

[Spring] Swagger 연동 시 Unable to infer base url 접속 에러 (ResponseBodyAdvice)
📡 백엔드/🌱 Spring Boot

[Spring] Swagger 연동 시 Unable to infer base url 접속 에러 (ResponseBodyAdvice)

2022. 8. 11. 21:25

Unable to infer base url. This is common when using dynamic servlet registration or when the API is behind an API Gateway. The base url is the root of where all the swagger resources are served. For e.g. if the api is available at http://example.org/api/v2/api-docs then the base url is http://example.org/api/.
Please enter the location manually: 

스웨거 사용 중인 스프링 부트 서버에서

기능 업그레이드 중 갑작스럽게 나타난 에러

 

원래는 이런 메세지 안떴는데 갑자기 떴다

 

구글링해도 다 뻔한 소리들 뿐이라서 좀 헤맸는데

다행스럽게 원인을 찾아냈다

 

 

 

💻 Project Dependency

...
	id 'org.springframework.boot' version '2.7.1'
...
...
	implementation 'io.springfox:springfox-boot-starter:3.0.0'
	implementation 'io.springfox:springfox-swagger-ui:3.0.0'
...

Spring Boot 2.7.1 그리고 Spring fox 3.0 사용 중이다

다운 그레이드를 하면 된다 안된다 말도 있는데 설정만 잘해주면 상관이 없다

 

 

 

💻 설정 파일

📝 SwaggerConfig.java

@Configuration
@EnableWebMvc
public class SwaggerConfig {

    private ApiInfo swaggerInfo() {
        return new ApiInfoBuilder()
                .title("HIFI Api Docs")
                .version("0.0.1")
                .description("HIFI Api 문서입니다")
                .build();
    }

    @Bean
    public Docket swaggerApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .securityContexts(Arrays.asList(securityContext()))
                .securitySchemes(Arrays.asList(apiKey()))
                .ignoredParameterTypes(AuthenticationPrincipal.class)
                .consumes(getConsumeContentTypes())
                .produces(getProduceContentTypes())
                .apiInfo(swaggerInfo()).select()
                .apis(RequestHandlerSelectors.basePackage("Backend.HIFI"))
                .paths(PathSelectors.any())
                .build();
    }

    private SecurityContext securityContext() {
        return SecurityContext.builder()
                .securityReferences(defaultAuth())
                .build();
    }
    private List<SecurityReference> defaultAuth() {
        AuthorizationScope authorizationScope = new AuthorizationScope(
                "global",
                "accessEverything"
        );
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        return Arrays.asList(new SecurityReference("Authorization", authorizationScopes));
    }
    private ApiKey apiKey() {
        return new ApiKey("Authorization", "X-AUTH-TOKEN", "header");
    }
    private Set<String> getConsumeContentTypes() {
        Set<String> consumes = new HashSet<>();
        consumes.add("application/json;charset=UTF-8");
        consumes.add("application/x-www-form-urlencoded");
        return consumes;
    }

    private Set<String> getProduceContentTypes() {
        Set<String> produces = new HashSet<>();
        produces.add("application/json;charset=UTF-8");
        return produces;
    }
}

설정 파일도 이상이 없다

 

 

🔨 해결 방안 1 - 스프링 시큐리티 설정

📝 SecurityConfiguration.java

@EnableWebSecurity
@RequiredArgsConstructor
@Configuration
public class SecurityConfiguration {
    private static final String[] SwaggerPatterns = {
            "/swagger-resources/**",
            "/swagger-ui.html",
            "/v2/api-docs",
            "/webjars/**"
    };
    
    ...
    
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                ...
                ...
                .antMatchers(SwaggerPatterns).permitAll()
                ...
                ...

                http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
                return http.build();
    }

만약 스프링 시큐리티를 사용 중이라면

스프링 시큐리티 설정 파일에서 Swagger 가 사용 중인 url에서

보안 설정을 끄는 방법이 해결 방안 중 하나이다

저 위에 있는 4가지 url 패턴을 스프링 시큐리티에서 허용해주면 된다

 

"/swagger-resources/**",
"/swagger-ui.html",
"/v2/api-docs",
"/webjars/**"

 

하지만 보안 설정을 해줬음에도 오류는 사라지지 않아서 다시 검색하다가

해결책을 발견했다

 

 

🔨 해결 방안 2 - @ControllerAdvice 설정

https://stackoverflow.com/questions/64473435/controlleradvice-does-not-allow-swagger-ui-to-be-displayed

 

@ControllerAdvice does not allow Swagger UI to be displayed

I just add a GlobalExceptionHandler with @ControllerAdvice and when i try to access Swagger UI at http://localhost:8080/swagger-ui/index.html?configUrl=/v3/api-docs/swagger-config#/ a get a message...

stackoverflow.com

 

📝 ResponceAdvice.java

@RestControllerAdvice                                                                   
public class ResponseAdvice implements ResponseBodyAdvice<Object> {                     
                                                                                        
    @Override                                                                           
    public boolean supports(                                                            
            MethodParameter returnType,                                                 
            Class<? extends HttpMessageConverter<?>> converterType)                     
    {                                                                                   
        return true;                                                                    
    }                                                                                   
                                                                                        
    @Override                                                                           
    public Object beforeBodyWrite(                                                      
            Object body,                                                                
            MethodParameter returnType,                                                 
            MediaType selectedContentType,                                              
            Class<? extends HttpMessageConverter<?>> selectedConverterType,             
            ServerHttpRequest request, ServerHttpResponse response)                     
    {                                                                                   
        if (body instanceof ErrorResponse)                                              
            return ResponseUtil.onError((ErrorResponse) body);                          
        return ResponseUtil.onSuccess(body);                                            
    }                                                                                   
}

모든 문제는 바로 이 ResponseBodyAdvice의 구현체로

@RestControllerAdvice 를 추가해서 발생했다

 

글로벌 익셉션 핸들러와 글로벌 리스폰스 핸들러를 구현한 이후부터 이 문제가 발생해서

바로 띠용했다

이유는 스웨거 응답까지 이 글로벌 리스폰스 핸들러를 거쳐서 가기 때문에

충돌이 발생하는 것이다

 

편하려고 구현한 controller advice 에 뒷통수를 세게 맞았다

 

해결책 중 하나는 basePackage를 설정해서

컨트롤러 범위를 지정해주는 것이다

@RestControllerAdvice(basePackages = {"Backend.HIFI.controller"})
public class ResponseAdvice implements ResponseBodyAdvice<Object> {
	...
}

 

이렇게 스웨거 설정 파일이 없는 디렉토리만 지정해주면 잘 된다

 

하지만 나는 도메인 기반 디렉토리 구조를 사용 중이라

더 좋은 해결방안을 고민해봐야겠다

저작자표시 (새창열림)

'📡 백엔드 > 🌱 Spring Boot' 카테고리의 다른 글

[Spring] 스프링 Feign Client 적용하기 (Spring Cloud OpenFeign)  (1) 2023.03.25
[Spring] 스프링 시큐리티 + JWT로 카카오 로그인 구현하기, 프론트엔드와 연결  (0) 2022.09.04
[Spring] OAuth2Service + 스프링 시큐리티 + JWT로 카카오 로그인 구현하기  (0) 2022.08.27
[Spring] 스프링 시큐리티로 CORS와 preflight 설정하기  (0) 2022.08.11
[Spring] 스프링 부트 프로젝트에서 dotenv 환경변수 파일 사용하기  (1) 2022.08.03
    '📡 백엔드/🌱 Spring Boot' 카테고리의 다른 글
    • [Spring] 스프링 시큐리티 + JWT로 카카오 로그인 구현하기, 프론트엔드와 연결
    • [Spring] OAuth2Service + 스프링 시큐리티 + JWT로 카카오 로그인 구현하기
    • [Spring] 스프링 시큐리티로 CORS와 preflight 설정하기
    • [Spring] 스프링 부트 프로젝트에서 dotenv 환경변수 파일 사용하기
    gengminy
    gengminy
    코딩

    티스토리툴바