MSA 기반 프로젝트의 SCG(Spring Cloud GateWay)에서 micro-service의 Swagger (OpenAPI) 통합 구현 연동
Registry Application (Eureka Server)
Client Applications
Spring cloud Gateway
ext {
set('springCloudVersion', "2020.0.3")
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'io.projectreactor:reactor-test'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
spring.application.name: registry
server.port: 8761
eureka:
client:
register-with-eureka: false
fetch-registry: false
*Eureka clients will look for port 8761 by default.
@EnableEurekaServer
@SpringBootApplication
public class RegistryAppApplication {
public static void main(String[] args) {
SpringApplication.run(RegistryAppApplication.class, args);
}
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-r2dbc'
implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
... 이하 생략
}
spring:
application:
name: board
...이하 생략
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
implementation 'org.springframework.cloud:spring-cloud-starter-sleuth'
implementation 'org.springdoc:springdoc-openapi-webflux-ui:1.5.10'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'io.projectreactor:reactor-test'
}
spring.application:
name: gateway
spring.output:
ansi.enabled: always # colorize console logs
logging:
file:
name: ./logs/${spring.application.name}.log
logback.rollingpolicy.max-history: 7
level:
root: INFO
server:
port: 8080
shutdown: graceful
# forward-headers-strategy: framework #
# # use-forward-headers: true
# error.whitelabel.enabled: false
#
##springdoc.show-actuator: true
#
management:
endpoints:
web:
exposure:
include:
- "gateway"
endpoint:
gateway:
enabled: true
health:
show-details: always
#springdoc.api-docs.path : /gw
spring.cloud.gateway:
default-filters:
- name: GlobalFilter
args:
baseMessage: Spring Cloud Gateway GlobalFilter
preLogger: true
postLogger: true
routes:
- id: openapi
uri: http://localhost:${server.port}
predicates:
- Path=/v3/api-docs/**
filters:
- RewritePath=/v3/api-docs/(?<path>.*), /$\{path}/v3/api-docs
- id: board-service
uri: lb://board
predicates:
- Path=/board/**
filters:
- RewritePath=/board/(?<path>.*), /$\{path}
- id: board2-service
uri: lb://board2
predicates:
- Path=/board2/**
filters:
- RewritePath=/board2/(?<path>.*), /$\{path}
-service
suffix is given to separate micro service routes and open-api route.
Path and Rewrite-path may defer by given environment.
For some reason, setting forward-headers-strategy: framework
breaks swagger. Not setting at all has not given such side-effect so far.
default-filters
is optional setting.
To enable swagger for gateway itself, you can simply add route with application name. Perhaps you could use variable as below.
- id: ${spring.application.name}-service
uri: lb://${spring.application.name}
predicates:
- Path=/${spring.application.name}/**
filters:
- RewritePath=/${spring.application.name}/(?<path>.*), /$\{path}
@Configuration
public class SwaggerConfig {
@Bean
public CommandLineRunner openApiGroups(
RouteDefinitionLocator locator,
SwaggerUiConfigParameters swaggerUiParameters) {
return args -> locator
.getRouteDefinitions().collectList().block()
.stream()
.map(RouteDefinition::getId)
.filter(id -> id.matches(".*-service"))
.map(id -> id.replace("-service", ""))
.forEach(swaggerUiParameters::addGroup);
}
}
This CommandLineRunner
will be ran once after application context has loaded and started.
I added open-api route to application.yml
to rewrite open-api request into corrent form.
RouterDefinitionLocater gives list of routes we'd like to add, filters non-service route, removes -service
suffix, and finally add groups to SwaggerUiConfigParameters.
localhost:8080/swagger-ui.html
API call test
The way of adding groups to openApi might differ in later releases. Please refer this post is using version 1.5
.
If on version 1.2
or below, see this document.
Get more information from official document
Examples for using GroupedOpenApi
here.
Original reference here.
Simplified my code while keeping concepts.
spring:
application:
name: board
springdoc.api-docs.path : /openapi/${spring.application.name}
...이하 생략
...
springdoc.api-docs.path : /openapi
spring.cloud.gateway:
default-filters:
- name: GlobalFilter
args:
baseMessage: Spring Cloud Gateway GlobalFilter
preLogger: true
postLogger: true
routes:
- id: ${spring.application.name}
uri: lb://${spring.application.name}
predicates:
- Path=/openapi/${spring.application.name}
filters:
- RewritePath=/openapi/${spring.application.name}, /openapi
- id: sign
uri: lb://sign
predicates:
- Path=/openapi/sign, /api/*/sign/**
- id: board
uri: lb://board
predicates:
- Path=/openapi/board, /api/*/board/**
...
...
@Bean
public CommandLineRunner openApiGroups(RouteDefinitionLocator locator, SwaggerUiConfigParameters swaggerUiParameters) {
return args -> locator
.getRouteDefinitions().collectList().block()
.stream()
.map(RouteDefinition::getId)
.forEach(swaggerUiParameters::addGroup);
}
...
삭제된 댓글입니다.