티스토리 뷰

2.1.0.RELEASE 문서를 번역한 내용

https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.1.0.RELEASE/single/spring-cloud-gateway.html

 

Spring Cloud Gateway

2.1.0.RELEASE This project provides an API Gateway built on top of the Spring Ecosystem, including: Spring 5, Spring Boot 2 and Project Reactor. Spring Cloud Gateway aims to provide a simple, yet effective way to route to APIs and provide cross cutting con

cloud.spring.io

1.  Spring Cloud Gateway 를 포함시키는 방법

프로젝트에 Spring Cloud Gateway 를 포함시키기 위해서는 org.springframework.cloud 로 시작하는 group 과 spring-cloud-starter-gateway 의 artifact id 를 사용해야 한다. Spring Cloud Project 페이지에서 자세한 세팅 방법을 확인할 수 있다.

 

stater 를 사용하지만 gateway 를 disable 하고 싶다면 아래 설정값을 추가하면 된다.

spring.cloud.gateway.enabled=false

 

Spring Boot + Spring Cloud Gateay build.gradle 예시

plugins {
	id 'org.springframework.boot' version '2.3.1.RELEASE'
	id 'io.spring.dependency-management' version '1.0.9.RELEASE'
	id 'java'
}

group = 'com.woongs'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter'
	testImplementation('org.springframework.boot:spring-boot-starter-test') {
		exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
	}
	compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-gateway', version: '2.2.1.RELEASE'
	
	compile group: 'log4j', name: 'log4j', version: '1.2.17'
	compile "org.projectlombok:lombok:1.16.6"
}

test {
	useJUnitPlatform()
}

 

2.  용어 설명

  • Route : Route 는 Gateway 를 이루는 기본 단위. ID 로 정의되며, 도착 URI, predicate 들과 filter 들의 모음이다. predicate 가 모두 충족되면 Route 가 매칭된다.
  • Predicate : Java8 Function Predicate 이다. Input 타입은 Spring Framework 의 ServerWebExchange 이다. Header 와 Parameter 와 같은 HTTP 구성 요소들로 개발자가 Matching 여부를 판단할 수 있도록 도와준다.
  • Filter : Spring Framework 의 GatewayFilter 이다. downstream 으로 요청을 보내기 전과 후에 Request 와 Response 를 수정할 수 있게 해준다.

3. 동작 원리

 

클라이언트가 Spring Cloud Gateway 로 요청을 보낸다. 만약 Gateway Handler Mapping 이 Route 에 요청이 매칭되었다고 판단한다면, Gateway Web Handler 로 요청을 보낸다. Gateway Web Handler 는 해당 요청에 특정된 필터 체인을 통하여 요청을 보내게 된다. 필터들이 점선으로 나뉘어진 이유는 Proxy Request 가 보내지기 전 또는 후에 실행되기 때문이다. 모든 "pre" 필터 로직이 실행된 후에 Proxy Request 가 생성되며 Proxy Request 가 생성된 후에 "post" 필터 로직이 수행된다.

 

4. Route Predicate Factories

Spring Cloud Gateway 는 Spring WebFlux 의 HandlerMapping 구조로 Route 를 매칭한다. Spring Cloud Gateway 는 많은 종류의 Route Predicate Factory 를 포함하고 있다. 이 모든 predicate 들은 HTTP 요청의 서로 다른 속성을 매칭시킬 수 있다. 여러개의 Multiple Route Predicate Factory 들은 "and" 를 이용하여 결합될 수 있다.

 

4.1 After Route Predicate Factory

After Route Predicate Factory 는 DateTime 을 파라미터로 받는다. 현재 DateTime 이후에 발생한 요청들에 대해서 매칭된다.

spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: http://example.org
        predicates:
        - After=2017-01-20T17:42:47.789-07:00[America/Denver]

2017년 1월 20일 17:42 이후에 생성된 요청들에 대해서 Route 가 매칭된다.

 

4.2 Before Route Predicate Factory

Before Route Predicate Factory 는 DateTime 을 파라미터로 받는다. 현재 DateTime 이전에 발생한 요청들에 대해서 매칭된다.

spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: http://example.org
        predicates:
	- Before=2017-01-20T17:42:47.789-07:00[America/Denver]

2017년 1월 20일 17:42 이전에 생성된 요청들에 대해서 Route 가 매칭된다.

 

4.3 Between Route Predicate Factory

Between Route Predicate Factory 는 두개의 DateTime 파라미터를 받는다. DateTime1 과 DateTime2 사이에 발생한 요청들에 대해서 매칭된다.

 

spring:
  cloud:
    gateway:
      routes:
      - id: between_route
        uri: http://example.org
        predicates:
        - Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]

2017년 1월 20일 17:42 부터 2017년 1월 21일 17:42 까지 발생한 요청들에 대해서 매칭되며 시스템 조정 등에 사용될 수 있다.

 

4.4 Cookie Route Predicate Factory

Cookie Route Predicate Factory 는 Cookie 이름과 정규표현식을 파라미터로 받는다. 주어진 쿠키 이름과 해당 값이 정규표현식에 매칭되면 매칭된다.

spring:
  cloud:
    gateway:
      routes:
      - id: cookie_route
        uri: http://example.org
        predicates:
        - Cookie=chocolate, ch.p

chocolate 이라는 쿠키를 가지고 있으며 value 가 ch.p 정규표현식에 매칭되면 해당 Route 가 매칭된다.

 

4.5 Header Route Predicate Factory

Header Route Predicate Factory 는 헤더 이름과 정규표현식을 파라미터로 받는다. 해당 헤더를 가지고 있으며 값이 정규표현식에 맞는다면 매칭된다. 

spring:
  cloud:
    gateway:
      routes:
      - id: header_route
        uri: http://example.org
        predicates:
        - Header=X-Request-Id, \d+

X-Request-Id 를 헤더로 가지고 있으며 값이 \d+ 에 맞는다면 매칭된다. (하나 이상의 digit)

 

4.6 Host Route Predicate Factory

Host Route Predicate Factory 는 호스트 패턴 리스트를 파라미터로 받는다. 이 패턴은 Ant 스타일 패턴이며 . 를 구분자로 사용한다.

이 predicate 는 Host 헤더가 패턴에 일치하는지 확인한다.

spring:
  cloud:
    gateway:
      routes:
      - id: host_route
        uri: http://example.org
        predicates:
        - Host=**.somehost.org,**.anotherhost.org

이 Route 는 요청이 Host 헤더를 포함하고 있으며 Value 가 www.somehost.org 또는 beta.somehost.org 또는 www.anotherhost.org  일 경우에 매칭된다. 

 

Host Route Predicate 는 URI Template 값을 이름과 값 Map 으로 추출하여 ServerWebExchange.getAttributes() 에 저장한다. 이때 키는 ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE 이다. 이 변수들은 GatewayFilter Factories 에서도 사용 가능하다.

 

4.7 Method Route Predicate Factory

Method Route Predicate Factory 는 HTTP 메소드를 파라미터로 사용한다.

spring:
  cloud:
    gateway:
      routes:
      - id: method_route
        uri: http://example.org
        predicates:
        - Method=GET

Request Method 가 GET 인 경우에 매칭된다.

 

4.8 Path Route Predicate Factory

Path Route Predicate Factory 는 Spring 의 PathMatcher 패턴 리스트와 matchOptionalTrailingSeparator 를 옵셔널 플래그로 사용한다.

spring:
  cloud:
    gateway:
      routes:
      - id: host_route
        uri: http://example.org
        predicates:
        - Path=/foo/{segment},/bar/{segment}

위 Route 는 Request Path 가 /foo/1 또는 /foo/gar 또는 /bar/baz 일 경우에 매칭된다.

 

Host Route Predicate 는 URI Template 값을 이름과 값 Map 으로 추출하여 ServerWebExchange.getAttributes() 에 저장한다. 이때 키는 ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE 이다. 이 변수들은 GatewayFilter Factories 에서도 사용 가능하다.

 

이 값들을 더 쉽게 사용하기 위한 유티리티 메서드가 존재한다.

Map<String, String> uriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange);

String segment = uriVariables.get("segment");

4.9 Query Route Predicate Factory

Query Route Predicate Factory 는 Param 을 필수로 regexp 를 옵셔널로 파라미터에 사용한다.

spring:
  cloud:
    gateway:
      routes:
      - id: query_route
        uri: http://example.org
        predicates:
        - Query=baz

baz 를 쿼리 파라미터로 사용하는 요청에 매칭된다.

spring:
  cloud:
    gateway:
      routes:
      - id: query_route
        uri: http://example.org
        predicates:
        - Query=foo, ba.

foo 를 쿼리 파라미터로 사용하고 value 가 ba. 정규 표현식에 맞는다면 매칭된다.

4.10 Retmote Addr Route Predicate Factory

최소 하나 이상의 CIDR (IPv4 또는 IPv6) 를 파라미터로 받는다.

spring:
  cloud:
    gateway:
      routes:
      - id: remoteaddr_route
        uri: http://example.org
        predicates:
        - RemoteAddr=192.168.1.1/24

remote address 가 CIDR 에 맞는다면 매칭된다. (192.168.1.10)

 

4.10.1 remote address 가 수정되는 경우

기본적으로 RemoteAddr Route Predicate Factory 는 들어오는 요청의 remote address 를 사용한다. 하지만 만약 Spring Cloud Gateway 가 Proxy 레이어 이후에 있다면 remote address 는 실제 Client 의 IP 가 아닐 수 있다.

 

따라서 RemoteAddressResolver 를 커스터마이징 한다면 이 문제를 해결할 수 있다. Spring Cloud Gateway 는 X-Forwarded-For header 를 사용하는 XForwardedRemoteAddressResolver 를 기본으로 사용한다. 

 

XForwardedRemoteAddressResolver 는 두개의 생성자 메서드를 제공한다.

 

  1. XForwardedRemoteAddressResolver::trustAll 는 X-Forwarded-For 헤더에 첫번째 IP 를 사용하는 RemoteAddressResolver 를 리턴한다. 
  2. XForwardedRemoteAddressResolver::maxTrustedIndex 는 Spring Cloud Gateway 앞단에서 실행되고 있는 시스템들의 갯수를 index 로 받는다. 만약 Spring Cloud Gateway 가 HAProxy 를 통해서 접근할 수 있다면 index 는 1이 되어야 한다. 만약 2개의 시스템이 Spring Cloud Gateway 앞에 있다면 index 는 2가 되어야 한다.
X-Forwarded-For: 0.0.0.1, 0.0.0.2, 0.0.0.3

Spring Cloud Gateway 가 받는 요청의 헤더에 위와 같이 전달된다면 maxTrustedIndex 는 아래와 같이 동작하게 된다.

 

[Integer.MIN_VALUE,0]

(invalid, IllegalArgumentException during initialization)

1

0.0.0.3

2

0.0.0.2

3

0.0.0.1

[4, Integer.MAX_VALUE]

0.0.0.1

Java config 예제

RemoteAddressResolver resolver = XForwardedRemoteAddressResolver
    .maxTrustedIndex(1);

...

.route("direct-route",
    r -> r.remoteAddr("10.1.1.1", "10.10.1.1/24")
        .uri("https://downstream1")
.route("proxied-route",
    r -> r.remoteAddr(resolver,  "10.10.1.1", "10.10.1.1/24")
        .uri("https://downstream2")

 

5. GatewayFilter Factories

Route Filter 는 들어오는 HTTP Request 와 나가는 HTTP Response 를 몇몇 방법을 통하여 수정할 수 있다. Spring Cloud Gateway 는 많은 구현된 GatewayFilter Factory 를 제공한다.

 

더 자세한 코드레벨을 보고 싶다면 여기를 참고!

 

5.1 AddRequestHeader Gateway Filter Factory

AddRequestHeader Gateway Filter Factory 는 name 과 value 를 파라미터로 받는다.

spring:
  cloud:
    gateway:
      routes:
      - id: add_request_header_route
        uri: http://example.org
        filters:
        - AddRequestHeader=X-Request-Foo, Bar

모든 매칭되는 요청에 대해서 X-Request-Foo:Bar 를 헤더에 추가한다.

 

5.2 AddRequestParameter GatewayFilter Factory

name 과 value 두개의 파라미터를 받는다.

spring:
  cloud:
    gateway:
      routes:
      - id: add_request_parameter_route
        uri: http://example.org
        filters:
        - AddRequestParameter=foo, bar

매칭 되는 모든 요청에 대해서 Request Query String 이 추가된다 (foo=bar)

 

5.3 AddResponseHeader GatewayFilter Factory

name 과 value 를 파라미터로 받는다.

spring:
  cloud:
    gateway:
      routes:
      - id: add_request_header_route
        uri: http://example.org
        filters:
        - AddResponseHeader=X-Response-Foo, Bar

매칭 되는 모든 요청에 대해서 X-Response-Foo:Bar 를 헤더에 추가한다.

 

5.4 Hystrix GatewayFilter Factory

HystrixCircurit Breaker Pattern 을 구현한 넷플릭스에서 만든 라이브러리이다. Hystrix GatewayFilter 는 Gateway Route 에 Circurit breaker 를 도입할 수 있게 해준다. 이는 서비스가 연속적으로 실패하는것으로부터 보호할 수 있으며 downstream 의 장애 발생시 fallback 응답을 제공할 수 있게 해준다.

 

Hystrix GatewayFilter 를 사용하기 위해서는 spring-cloud-starter-netflix-hystrix 를 의존성에 추가해야한다. 

 

Hystrix GatewayFilter Factory 는 name 파라미터를 받는다. 이 것은 HystrixCommand 의 이름이다.

spring:
  cloud:
    gateway:
      routes:
      - id: hystrix_route
        uri: http://example.org
        filters:
        - Hystrix=myCommandName

Hystrix 필터는 fallbackUri 파라미터를 선택적으로 받을 수 있다. 현재 오로지 forward: 만 허용된다. fallback 이 불리게 되면 URI 에 매칭되는 컨트롤러로 포어드 된다.

 

spring:
  cloud:
    gateway:
      routes:
      - id: hystrix_route
        uri: lb://backing-service:8088
        predicates:
        - Path=/consumingserviceendpoint
        filters:
        - name: Hystrix
          args:
            name: fallbackcmd
            fallbackUri: forward:/incaseoffailureusethis
        - RewritePath=/consumingserviceendpoint, /backingserviceendpoint

 Hystrix fallback 이 불리게 되면 /incaseoffailuresethis 로 포워딩 한다. 이 예제는 Spring Cloud Netflix Ribbon 의 load-balancing 을 도착 URI prefix 로 사용하고 있다.

 

기본적으로 fallbackUri 는 Spring Cloud Gateway 내부의 Controller 로 맵핑되지만 외부 application 으로 reroute 하는 것도 가능하다.

spring:
  cloud:
    gateway:
      routes:
      - id: ingredients
        uri: lb://ingredients
        predicates:
        - Path=//ingredients/**
        filters:
        - name: Hystrix
          args:
            name: fetchIngredients
            fallbackUri: forward:/fallback
      - id: ingredients-fallback
        uri: http://localhost:9994
        predicates:
        - Path=/fallback

위 예제에서는 fallback endpoint 또는 gateway application 의 핸들러가 존재하지 않지만 http://localhost:9994 아래에 등록되어있는 또 다른 app 이 존재한다.

 

fallback 으로 요청이 포워딩 되는 경우에, Hystrix GatewayFilter 는 Fallback 의 원인이 되는 Throwable 를 제공한다.  ServerWebExchange 에 ServerWebExchangeUtils.HYSTRIX_EXECUTION_EXCEPTION_ATTR 속성을 추가해준다.

 

Exception Detail 이 헤더에 추가될 수 있다. 자세한 내용은 FallBackHeaders GatewayFilter Factory section 에서 참고할 수 있다.

 

Hystrix 설정은 Global 기본 설정을 사용할 수도 있고 Route 별로 설정을 할 수 있다. 여기 참고.

 

5.5 FallbackHeaders GatewayFilter Factory

FallbackHeaders Factory 는 Hystrix 실행 예외의 디테일한 정보를 헤더에 포함시켜 fallbackUri 로 전달할 수 있다.

spring:
  cloud:
    gateway:
      routes:
      - id: ingredients
        uri: lb://ingredients
        predicates:
        - Path=//ingredients/**
        filters:
        - name: Hystrix
          args:
            name: fetchIngredients
            fallbackUri: forward:/fallback
      - id: ingredients-fallback
        uri: http://localhost:9994
        predicates:
        - Path=/fallback
        filters:
        - name: FallbackHeaders
          args:
            executionExceptionTypeHeaderName: Test-Header

HystrixCommand 를 실행하는 도중에 발생한 예외를 실행한 후에 fallback 엔드포인트인 localhost:9994 로 포워딩 될 것이다. 헤더에는 Exception Type, 메시지 그리고 가능하다면 root cause exception type 과 메시지가 FallbackHeaders 필터에 의해서 추가될 것이다.

 

5.6 PrefixPath GatewayFilter Factory

prefix 를 파라미터로 받는다.

spring:
  cloud:
    gateway:
      routes:
      - id: prefixpath_route
        uri: http://example.org
        filters:
        - PrefixPath=/mypath

매칭되는 모든 요청에 /mypath 를 경로에 prefix 로 추가한다. /hello 요청이 들어온다면 /mypath/hello 

 

5.7 PreserveHostHeader GatewayFilter Factory

PreseveHostHeader 는 파라미터가 없다. 이 필터는 http client 에 의해서 host header 가 결정되었는지를 확인한다. 

spring:
  cloud:
    gateway:
      routes:
      - id: preserve_host_route
        uri: http://example.org
        filters:
        - PreserveHostHeader

 

5.8 RequestRateLimiter GatewayFilter Factory

RequestRateLimiter GatewayFilter 는 현재 요청이 처리되어도 되는지 결정하기 위하여 RateLimiter 를 구현한다. 만약 처리될 수 없다면 디폴트로 HTTP 429 - Too Many Requests 를 리턴한다. 

 

필터는 옵션으로 keyResolver 를 파라미터로 받는다. 이 파라미터는 RateLimit 에 사용할 키를 특정한다.

 

keyResolverKeyResolver 를 구현한 빈이다. 

public interface KeyResolver {
	Mono<String> resolve(ServerWebExchange exchange);
}

KeyResolver 는 요청을 제한할때 사용할 키를 변경할 수 있도록 도와준다. 앞으로는 KeyResolver 구현체가 생길것이다.

 

디폴트로는 PrincipalNameKeyResolver 를 사용하게 된다. 이 리졸버는 PrincipalServerWebExchange 로 부터 얻어오고 Principal 에서 Pincipal.getName() 을 호출한다. 

 

KeyResolver 가 키를 찾지 못한다면 디폴트 정책은 해당 요청을 막는다. 위 설정은 아래 설정값으로 변경될 수 있다.

  • spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key : ture
  • spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code

5.8.1 Redis RateLimiter

Redis 를 사용하기 위해서는 아래 의존성이 추가되어야 한다.

spring-boot-starter-data-redis-reactive

 

이때 사용되는 알고리즘은 Token Bucket Algorithm 이다.

 

  • redis-rate-limiter.replenishRate : 1초당 몇개까지 요청을 허용할지에 대한 속성 값이다. token buket 이 가득 차는 값. token bucket 에서 downstream 으로 흐르는 요청양 같다.
  • redis-rate-limiter.burstCapacity : 1초에 최대 몇개까지 요청을 보낼 수 있는지에 대한 속성 값이다. token bucket 이 가지고 있을 수 있는 토큰 갯수이다. 이 값을 0 으로 설정하면 모든 요청이 block 된다

replenishRateburstCapacity 를 같은 값으로 설정하면 동일한 값이 적용된다. 일시적으로 제한을 걸기 위해서는 burstCapacity 를 replenishRate 보다 큰 값으로 설정하면 된다. 이 경우에 Rate Limiter 는 replenishRate 에 따라서 허용된다. 2번의 연이은 초과는 요청이 블락되는 결과를 낳는다.

spring:
  cloud:
    gateway:
      routes:
      - id: requestratelimiter_route
        uri: http://example.org
        filters:
        - name: RequestRateLimiter
          args:
            redis-rate-limiter.replenishRate: 10
            redis-rate-limiter.burstCapacity: 20
@Bean
KeyResolver userKeyResolver() {
    return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}

위 설정은 하나의 사용자당 10개의 요청을 제한한다. 20건 까지 bucket 에 담기는 것을 허용하지만, 다음 1초 동안 10 건의 요청만 가능하다. 

 

RateLimiter 를 구현하면 커스터마이징된 RateLimiter 를 사용할 수 있다. 설정에 보면 #{@myRateLimiter} 와 같이 사용한다.

 

spring:
  cloud:
    gateway:
      routes:
      - id: requestratelimiter_route
        uri: http://example.org
        filters:
        - name: RequestRateLimiter
          args:
            rate-limiter: "#{@myRateLimiter}"
            key-resolver: "#{@userKeyResolver}"

 

5.9 RedirectTo Gateway Filter Factory

status 과 url 을 파라미터로 받는다. Status 는 300 대의 응답 코드를 사용해야만 한다. 유효한 url 을 사용해야하며 이것은 Location header 의 값이 된다.

spring:
  cloud:
    gateway:
      routes:
      - id: prefixpath_route
        uri: http://example.org
        filters:
        - RedirectTo=302, http://acme.org

위 설정은 매칭되는 uri 에 대해서 리다이렉 시키기 위하여 헤더에 Location:http://acme.org 를 포함시킨다.

 

5.10 RemoveNonProxyHeaders GatewayFilter Factory

요청을 포워딩할때 헤더를 제거할 수 있다. 기본적으로 제거할 수 있는 헤더들의 리스트는 아래와 같다.

  • Connection
  • Keep-Alive
  • Proxy-Authenticate
  • Proxy-Authorization
  • TE
  • Trailer
  • Transfer-Encoding
  • Upgrade

위 리스트를 변경하고 싶다면 spring.cloud.gateway.filter.remove-non-proxy-headers.headers 프로퍼티에 제거하고자 하는 헤더 이름을 추가하면 된다.

 

5.11 RemoveRequestHeader GatewayFilter Factory

name 을 파라미터로 받으며 파라미터로 받은 name 을 헤더에서 제거한다.

spring:
  cloud:
    gateway:
      routes:
      - id: removerequestheader_route
        uri: http://example.org
        filters:
        - RemoveRequestHeader=X-Request-Foo

X-Request-Foo 헤더가 제거된 후에 downstream 시스템으로 전달된다.

 

5.12 RemoveResponseHeader GatewayFilter Factory

name 을 파라미터로 받으며 응답에서 name 헤더를 제거한다.

spring:
  cloud:
    gateway:
      routes:
      - id: removeresponseheader_route
        uri: http://example.org
        filters:
        - RemoveResponseHeader=X-Response-Foo

X-Response-Foo 헤더가 Rseponse 에서 제거되어 클라이언트에게 전달된다.

 

5.13 RewritePath GatewayFilter Factory

regexp 와 replacement 파리미터를 받는다. 유연한 rewrite path 를 위하여 자바 정규표현식을 사용한다.

spring:
  cloud:
    gateway:
      routes:
      - id: rewritepath_route
        uri: http://example.org
        predicates:
        - Path=/foo/**
        filters:
        - RewritePath=/foo/(?<segment>.*), /$\{segment}

/foo/bar 에 매칭되는 요청은 정규표현식에 의해서 /bar 로 수정되어 downstream 으로 전달된다. $₩ 신텍스는 YAML 스펙에 의해서 $ 로 변경되었다는것을 기억하자!

 

5.14 RewriteResponseHeader GateayFilter Factory

name, regexp 와 replacement 를 파라미터로 받는다. 

spring:
  cloud:
    gateway:
      routes:
      - id: rewriteresponseheader_route
        uri: http://example.org
        filters:
        - RewriteResponseHeader=X-Response-Foo, , password=[^&]+, password=***

헤더 값인 42?user=ford&password=omg!what&flag=true 는 RewriteResponseHeader 필터에 의해서 /42?user=ford&password=***&flag=true 로 변경된다.

 

5.15 SaveSession GatewayFilter Factory

SaveSession 필터는 WebSession::save 함수를 dwonstream 으로 요청을 전달하기 전에 강제적으로 호출한다. Spring Session 과 같이 lazy data store 와 downstream 으로 요청을 전달하기 전에 세션 상태가 저장되어야만 할때 사용된다.

spring:
  cloud:
    gateway:
      routes:
      - id: save_session
        uri: http://example.org
        predicates:
        - Path=/foo/**
        filters:
        - SaveSession

Spring Security 의 Spring Session 을 연동하여 사용하고 있고 다른 리모트에 보안 디테일을 보장하고 싶다면 이 기능이 영향을 미칠 것이다.

 

5.16 SecureHeaders GatewayFilter Factory

SecureHeaders 는 이 블로그에서 추천하는 많은 헤더들을 추가해준다.

  • X-Xss-Protection:1; mode=block
  • Strict-Transport-Security:max-age=631138519
  • X-Frame-Options:DENY
  • X-Content-Type-Options:nosniff
  • Referrer-Policy:no-referrer
  • Content-Security-Policy:default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline'
  • X-Download-Options:noopen
  • X-Permitted-Cross-Domain-Policies:none

위 기본값들을 변경하고 싶다면 아래 프로퍼티로 수정할 수 있다.

spring.cloud.gateway.filter.secure-headers

 

  • xss-protection-header
  • strict-transport-security
  • frame-options
  • content-type-options
  • referrer-policy
  • content-security-policy
  • download-options
  • permitted-cross-domain-policies

5.17 SetPath GatewayFilter Factory

template 을 파라미터로 받는다. 템플릿화된 부분을 이용하여 요청 Path 를 다룰 수 있게 해준다. Spring Framework 의 uri 템플렛을 사용한다. 

spring:
  cloud:
    gateway:
      routes:
      - id: setpath_route
        uri: http://example.org
        predicates:
        - Path=/foo/{segment}
        filters:
        - SetPath=/{segment}

/foo/bar 요청이 /bar 로 변경되어 downstream 에 전달된다.

 

5.18 SetResponseHeader GatewayFilter Factory

name 과 value 를 파라미터로 받는다.

spring:
  cloud:
    gateway:
      routes:
      - id: setresponseheader_route
        uri: http://example.org
        filters:
        - SetResponseHeader=X-Response-Foo, Bar

SetResponseHeader 는 헤더를 추가하는 것이 아니라 기존에 있는 헤더 값을 변경하는데 사용한다. 만약 downstream 시스템이 X-Response-Foo:1234 라는 값을 헤더에 포함시킨다면 X-Response-Foo:Bar 로 헤더값을 변경한다.

 

5.19 SetStatus GatewayFilter Factory

status 를 파리미터로 받는다. status 는 HttpStatus 의 유효한 값이 전달되어야 하나다. 404 와 같은 Integer 값 혹은 NOT_FOUND 같은 Enum 이 전달되어야 한다.

 

spring:
  cloud:
    gateway:
      routes:
      - id: setstatusstring_route
        uri: http://example.org
        filters:
        - SetStatus=BAD_REQUEST
      - id: setstatusint_route
        uri: http://example.org
        filters:
        - SetStatus=401

매칭되는 요청에대해서 HttpStatus 를 전달받은 값으로 설정한다.

 

5.20 StripPrefix GatewayFilter Factory

parts 를 파라미터로 받는다. 

spring:
  cloud:
    gateway:
      routes:
      - id: nameRoot
        uri: http://nameservice
        predicates:
        - Path=/name/**
        filters:
        - StripPrefix=2

http://nameservice/name/bar/foo 로 들어온 요청은 http://nameservice/foo 로 변경될 것이다.

 

5.21 Retry GatewayFilter Factory

retires, statuses, methods and series 를 파라미터로 받는다.

  • retries : 시도될 재시도 횟수.
  • statuses : 재시도될 HTTP 상태값들. org.springframework.http.HttpStatus
  • methods : 재시도될 HTTP Method 들. org.springframework.http.HttpMethod
  • series : 재시도될 Series. org.springframework.http.HttpStatus.Series
spring:
  cloud:
    gateway:
      routes:
      - id: retry_test
        uri: http://localhost:8080/flakey
        predicates:
        - Host=*.retry.com
        filters:
        - name: Retry
          args:
            retries: 3
            statuses: BAD_GATEWAY

5.22 RequestSize GatewayFilter Factory

설정된 값보다 request size 가 큰 경우에 요청을 제한할 수 있다. RequestSize 를 파라미터로 받는다. Byte 단위이다.

spring:
  cloud:
    gateway:
      routes:
      - id: request_size_route
      uri: http://localhost:8080/upload
      predicates:
      - Path=/upload
      filters:
      - name: RequestSize
        args:
          maxSize: 5000000

500000Byte 를 초과하는 request body 에 대해서 413 Payload Too Large 응답을 리턴하며 추가로 헤더에 errorMessage 에 최대 사이즈를 리턴해준다.

 

5.23 Modify Request Body GatewayFilter Factory < BETA 버전!

downstream 으로 요청을 전달하기 전에 Request Body 를 수정할 수 있다.

@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
    return builder.routes()
        .route("rewrite_request_obj", r -> r.host("*.rewriterequestobj.org")
            .filters(f -> f.prefixPath("/httpbin")
                .modifyRequestBody(String.class, Hello.class, MediaType.APPLICATION_JSON_VALUE,
                    (exchange, s) -> return Mono.just(new Hello(s.toUpperCase())))).uri(uri))
        .build();
}

static class Hello {
    String message;

    public Hello() { }

    public Hello(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

5.24 Modfy Response Body GatewayFilter Factory < BETA 버전!

Client 에게 응답을 전달하기 전에 Response Body 를 수정할 수 있다.

@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
    return builder.routes()
        .route("rewrite_response_upper", r -> r.host("*.rewriteresponseupper.org")
            .filters(f -> f.prefixPath("/httpbin")
        		.modifyResponseBody(String.class, String.class,
        		    (exchange, s) -> Mono.just(s.toUpperCase()))).uri(uri)
        .build();
}

6. Global Filters

GlobalFilter 는 GatewayFilter 와 같은 시그니쳐를 갖는다. 모든 Route 에 적용할 수 있는 특별한 필터이다.

 

6.1 Combined Global Filter and GatewayFilter Ordering

요청이 Gateway 로 인입되고 Route에 매칭되었을때 Filtering Web Handler 는 모든 객체에 GoblalFilter 를 추가한다. 그리고 모든 Route 의 Filter chain 에 Global Filter 를 추가한다. 이렇게 결합된 필터들은 org.springframework.core.Ordered 에 의해서 정렬된다. 

 

Spring Cloud Gateway 는 필터 로직을 수행할때 "pre" 와 "post" 를 구분하기 때문에, 가잔 우선순위가 높은 필터의 "pre" 필터가 먼저 수행되며 "post" 구문이 가장 늦게 수행된다.

 

@Bean
@Order(-1)
public GlobalFilter a() {
    return (exchange, chain) -> {
        log.info("first pre filter");
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            log.info("third post filter");
        }));
    };
}

@Bean
@Order(0)
public GlobalFilter b() {
    return (exchange, chain) -> {
        log.info("second pre filter");
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            log.info("second post filter");
        }));
    };
}

@Bean
@Order(1)
public GlobalFilter c() {
    return (exchange, chain) -> {
        log.info("third pre filter");
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            log.info("first post filter");
        }));
    };
}

 

6.2 Forward Routing Filter

Forward Routing Filter 는 excahnge 속성 값중 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 를 바라본다.

URL 에 forward scheme (forward://localendpoint) 를 가지고 있다면 Spring Cloud Gateway 는 이 요청을 처리하기 위하여 DispatcherHandler 를 사용한다.

요청 URL 의 Path 를 forward URL 로 엎어치게된다. 수정되지 않은 기존의 URL 은 ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR 에 저장된다.

 

6.3 LoadBalancerClient Filter

LoadBalancerClient 필터는 Exchange 속석 값중 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 를 바라본다. 만약 url 구조중에 lb scheme (lb://mysevice) 를 가지고 있다면, SPring Cloud 의 LoadBalancerClient 를 를 사용하여 myservice 의 실제 호스트와 포트를 찾아 URI 를 대체한다. 수정되지 않은 기존의 URL 은 ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR 속성에 저장된다.

spring:
  cloud:
    gateway:
      routes:
      - id: myRoute
        uri: lb://service
        predicates:
        - Path=/service/**

LoadBalancer 에서 서비스 인스턴스를 찾을 수 없다면 기본적으로 503 을 리턴한다.

아래 설정을 이용하여 404 로 변경할 수 있다.

spring.cloud.gateway.loadbalancer.use404=true

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함