Java/SpringBoot

[Spring Boot] Spring Cloud GateWay 필터 추가

JoJun's 2022. 6. 14. 12:15
728x90
반응형

스프링 부트에서는 Cloud 환경을 위한 Gateway 프레임워크를 제공한다.

 

mvn repository에 Maven이나 Gradle에 Dependency를 추가할 수 있도록 검색을 제공한다.

 

Maven Repository: org.springframework.cloud » spring-cloud-starter-gateway

 

mvnrepository.com

 

이 글에서는 PRE, POST 필터를 추가하는 방법을 제시한다.

제공되는 Filter의 종류

org.springframework.cloud.gateway에서 기본적으로 제공하는 필터는 아래와 같이 수십 개의 필터를 제공한다.

기본 filter들

 

 

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: lb://MY-FIRST-SERVICE
          predicates:
            - Path=/first-service/** 
          filters:
            - AddRequestHeader=first-request, first-request-header2
            - AddResponseHeader=first-request, first-request-header2
            - CustomFilter
        - id: second-service
          uri: lb://MY-SECOND-SERVICE
          predicates:
            - Path=/second-service/** 
          filters:
            - RemoveRequestHeader=Cookie
            - RewritePath=/second-service/(?<segment>.*), /$\{segment}
            - CustomFilter
            - name: LoggingFilter
              args:
                baseMessage: "Hi, there."
                preLogger: true
                postLogger: true
 

 

위 YML은  총 7개의 필터가 등록되어있다.   

 적용되는 라우팅 필터 종류 필터 설명
모든 라우팅 ( Global ) GlobalFilter Filter 스프링 클라우드 gateway에서 제공하지 않는 커스텀 필터로 모든 라우팅에 해당하는 요청에 필터 처리
first-service AddRequestHeader Filter 요청에 헤더를 추가하는 필터
AddResponseHeader Filter 응답에 헤더를 추가하는 필터
second-service RemoveRequestHeader FIlter 요청의 특정 헤더를 제거하는 필터
RewritePath Filter 요청 Path를 재 정의 하는 필터
LoggingFilter Filter 스프링 클라우드 gateway에서 제공하지 않는 커스텀 필터로 해당 글에서 설명하는 로깅 필터
first-service,
second-service
CustomFilter Filter  first, second 라우팅에 설정한 커스텀 필터

 

 

위 yml에 설정되어있는 필터만 사용가능한 것이 아니라 더 많은 필터를 설정할 수 있다.

yml에 필터별로 Config를 설정할 수 있는데 Config속성이 있다면 필터를 정의할 때 -name: 과 같이 정의를 해주어야 한다.

 

Filter

아래는 위에 정의된 필터들의 소스들이다   필터들은 모두 작성방법이 동일하다

추가로, org.springframework.cloud.gateway에서 제공하는 필터들도 동일한 방법대로 정의되어 있으니 한번 참고해보면 좋을 것 같다.

 

GlobalFilter

package com.example.apigatewayserver.filter;

import lombok.Data;
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;

/**
 * Class       : CustomFilter
 * Author      : Jun's
 * Description : Class Description
 * History     : [2022-06-10] - Jun's - Class Create
 */
@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.getBaseMessage());


            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 code -> {}", response.getStatusCode());
            }));

        });
    }

    @Data
    public static class Config{
        // Put the configuration properties...
        private String baseMessage;
        private boolean preLogger;
        private boolean postLogger;
    }
}

 

 

CustomFilter

package com.example.apigatewayserver.filter;

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;

/**
 * Class       : CustomFilter
 * Author      : Jun's
 * Description : Class Description
 * History     : [2022-06-10] - Jun's - Class Create
 */
@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 : response id -> {}", response.getStatusCode());
            }));

        });
    }

    public static class Config{
        // Put the configuration properties...
    }
}

 

 

LogginFilter

package com.example.apigatewayserver.filter;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.OrderedGatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

/**
 * Class       : LoggingFilter
 * Author      : Jun's
 * Description : Class Description
 * History     : [2022-06-10] - Jun's - Class Create
 */
@Component
@Slf4j
public class LoggingFilter extends AbstractGatewayFilterFactory<LoggingFilter.Config> {

    public LoggingFilter() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        // Logging Pre Filter

        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 : request id -> {}", request.getId());

            // Custom Post Filter
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                if(config.isPostLogger())
                    log.info("Logging POST filter : response code -> {}", response.getStatusCode());
            }));
        }, Ordered.LOWEST_PRECEDENCE);

        return filter;

    }

    @Data
    public static class Config{
        // Put the configuration properties...
        private String baseMessage;
        private boolean preLogger;
        private boolean postLogger;
    }
}

 

위와 같은  방법으로 JWT 필터를 게이트웨이에 추가할 수도 있고, Log를 작성할 수도 있고 여러 확장이 제공된다.

728x90
반응형