application.yml파일(Property)의 cloud.gateway.routes
설정을 주석처리 혹은 삭제한다.
# cloud:
# gateway:
# routes:
# - id: first-service
# uri: http://localhost:8081/
# predicates:
# - Path=/first-service/**
# - id: second-service
# uri: http://localhost:8082/
# predicates:
# - Path=/second-service/**
// FilterConfig.java
// 위의 property설정과 동일한 javacode
@Configuration
public class FilterConfig {
@Bean
public RouteLocator gatewayRoutes(RouteLocatorBuilder builder) {
return builder.routes()
.route(r -> r.path("/first-service/**")
.filters(f -> f.addRequestHeader("first-request","first-request-header")
.addResponseHeader("first-response","first-response-header"))
.uri("http://localhost:8081"))
.route(r -> r.path("/second-service/**")
.filters(f -> f.addRequestHeader("second-request","second-request-header")
.addResponseHeader("second-response","second-response-header"))
.uri("http://localhost:8082"))
.build();
}
}
@RestController
@RequestMapping("/first-service")
@Slf4j
public class FirstServiceController {
...
// header값을 "first-request"로 설정했기에 그 값의 value를 저장
@GetMapping("/message")
public String message(@RequestHeader("first-request") String header) {
log.info(header);
return "Hello world in First Service";
}
}
@RestController
@RequestMapping("/second-service")
@Slf4j
public class SecondServiceController {
...
// header값을 "second-request"로 설정했기에 그 값의 value를 저장
@GetMapping("/message")
public String message(@RequestHeader("second-request") String header) {
log.info(header);
return "Hello world in Second Service";
}
}
log와 웹 페이지에서 제대로 표시된 것을 확인할 수 있다.
// application.yml
...
spring:
application:
name: apigateway-service
cloud:
gateway:
routes:
- id: first-service
uri: http://localhost:8081/
predicates:
- Path=/first-service/**
filters:
- AddRequestHeader=first-request, first-request-header2
- AddResponseHeader=first-response, first-response-header2
- id: second-service
uri: http://localhost:8082/
predicates:
- Path=/second-service/**
filters:
- AddRequestHeader=second-request, second-request-header2
- AddResponseHeader=second-response, second-response-header2
filters 를 통해 필터를 걸 수 있다.
// application.yml
...
spring:
application:
name: apigateway-service
cloud:
gateway:
routes:
- id: first-service
uri: http://localhost:8081/
predicates:
- Path=/first-service/**
filters:
# - AddRequestHeader=first-request, first-request-header2
# - AddResponseHeader=first-response, first-response-header2
- CustomFilter
- id: second-service
uri: http://localhost:8082/
predicates:
- Path=/second-service/**
filters:
# - AddRequestHeader=second-request, second-request-header2
# - AddResponseHeader=second-response, second-response-header2
- CustomFilter
위에서 작성한 filter를 주석처리하고 CustomFilter를 넣는다.
JavaCode로 CustomFilter 생성
// CumtomFilter.java
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
@Component
@Slf4j
public class CustomFilter extends AbstractGatewayFilterFactory<CustomFilter.Config> {
public CustomFilter() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
// Custom Pre Filter
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
log.info("Custom PRE Filter: Request id -> {}", request.getId());
// Custom Post Filter
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
log.info("Custom POST Filter: Request id -> {}", response.getStatusCode());
}));
};
}
public static class Config {
// Put the configuration properties
}
}
API Gateway를 통해 Request, Response되는 것을 확인할 수 있다.
Service별로 Filter 적용하는게 아닌 전체를 일괄 적용하는 Filter
// GlobalFilter.java
@Component
@Slf4j
public class GlobalFilter extends AbstractGatewayFilterFactory<GlobalFilter.Config> {
public GlobalFilter() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
// Custom Pre Filter
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
log.info("Global Filter baseMessage: {}", config.getBaseMessaqge());
if(config.isPreLogger()) {
log.info("Global Filter Start: request id -> {}", request.getId());
}
// Custom Post Filter
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
if(config.isPostLogger()) {
log.info("Global Filter End: response id -> {}", response.getStatusCode());
}
}));
};
}
@Data
public static class Config {
// Put the configuration properties
private String baseMessaqge;
private boolean preLogger;
private boolean postLogger;
}
}![](https://velog.velcdn.com/images/jungse97/post/f7936680-bc2c-4f95-a426-82cc8acb425a/image.PNG)
// application.yml
...
spring:
application:
name: apigateway-service
cloud:
gateway:
default-filters:
- name: GlobalFilter
args:
baseMessage: Spring Cloud Gateway Global Filter
preLogger: true
postLogger: true
...
Global Filter start
> Custom Pre Filter
> Custom Post Filter
> Global Filter End
Global Filter 종료되기 전에 Custom Filter 로직이 적용되고 Global Filter 종료
// LoggingFilter.java
@Component
@Slf4j
public class LoggingFilter extends AbstractGatewayFilterFactory<LoggingFilter.Config> {
public LoggingFilter() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
GatewayFilter filter = new OrderedGatewayFilter((exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
log.info("Logging Filter baseMessage: {} ", config.getBaseMessage());
if (config.isPreLogger()) {
log.info("Logging PRE Filter Start: request id -> {}", request.getId());
}
//Custom Post Filter
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
if (config.isPostLogger()) {
log.info("Logging POST Filter End: response code -> {} ", response.getStatusCode());
}
}));
}, Ordered.LOWEST_PRECEDENCE); // 우선순위 지정할 수 있다
//HIGHEST_PRECEDENCE
return filter;
}
@Data
public static class Config {
private String baseMessage;
private boolean preLogger;
private boolean postLogger;
}
}
// application.yml
...
spring:
application:
name: apigateway-service
cloud:
gateway:
default-filters:
- name: GlobalFilter
args:
baseMessage: Spring Cloud Gateway Global Filter
preLogger: true
postLogger: true
routes:
- id: first-service
uri: http://localhost:8081/
predicates:
- Path=/first-service/**
filters:
# - AddRequestHeader=first-request, first-request-header2
# - AddResponseHeader=first-response, first-response-header2
- CustomFilter
- id: second-service
uri: http://localhost:8082/
predicates:
- Path=/second-service/**
filters:
# - AddRequestHeader=second-request, second-request-header2
# - AddResponseHeader=second-response, second-response-header2
- name: CustomFilter
- name: LoggingFilter
args:
baseMessage: Hi. there.
preLogger: true
postLogger: true
LOWEST_PRECEDENCE
적용 시 Global > Custom > Logging
HIGHEST_PRECEDENCE
적용 시 Logging > Global > Custom