【问题标题】:Having multiple request IPs in Spring WebTestClient在 Spring WebTestClient 中有多个请求 IP
【发布时间】:2022-01-18 08:13:31
【问题描述】:

我将在我的 Spring Web 应用程序中引入 Bucket4J。可以在此处找到基本测试设置:

Bucket4J 提供基于 IP 的速率限制 - 因此每个 IP 都有自己的令牌池。这可以通过在配置中添加expression: "getRemoteAddress()" 来完成:

bucket4j:
enabled: true
filters:
  - metrics:
    types:
      - consumed-counter
      - rejected-counter
  - cache-name: buckets
    filter-method: webflux
    url: .*
    filter-order: 1
    rate-limits:
      - bandwidths:
          - capacity: 1
            time: 10
            unit: seconds
        expression: "getRemoteAddress()"

我很难弄清楚如何以编程方式测试filter by IP 是否正常工作。

单个IP的测试如下:

@ActiveProfiles("test")
@SpringBootTest
class RateLimitTest(
    @Autowired val context: ApplicationContext
) {

@Test
fun `FAILS with status code 429 if rate limit is exceeded`() {
    // arrange
    val client = WebTestClient
        .bindToApplicationContext(context)
        .configureClient()
        .build()

    // ac
    client.get()
        .uri("/api/someendpoint")
        .exchange()
        .expectStatus().isOk
        .expectHeader().valueEquals("X-Rate-Limit-Remaining", "0")

    client.get()
        .uri("/api/someendpoint")
        .exchange()
        .expectStatus().isEqualTo(HttpStatus.TOO_MANY_REQUESTS)
        .expectBody().jsonPath("error", "Too many requests!")

    // assert

}

验证多个 IP 的行为/IP 速率限制的测试应该是什么样的?
FAILS with status code 429 if rate limit * for IP * is exceeded

【问题讨论】:

    标签: spring-webflux webtestclient bucket4j


    【解决方案1】:

    实际上我的方法总体上是错误的。有问题的应用程序位于负载均衡器后面,因此查询 getRemoteAddress() 只会给我负载均衡器的 IP。

    我必须使用标题X-FORWARDED-FOR,这使得为它创建测试变得超级容易?

    bucket4j:
      enabled: true
      filters:
        - metrics:
            types:
              - consumed-counter
              - rejected-counter
        - cache-name: buckets
          filter-method: webflux
          url: ^(/api/someendpoint).*
          filter-order: 1
          rate-limits:
            - bandwidths:
                - capacity: 1
                  time: 10
                  unit: seconds
              expression: "getHeaders()['X-FORWARDED-FOR']"
    

    对此的测试是

       @Test
        fun `SUCCESSFULLY rate by X-FORWARDED-FOR header`() {
        // arrange
       val endpoint = "/api/someendpoint"
    
        // act
        WebTestClient
            .bindToApplicationContext(context)
            .configureClient()
            .defaultHeader("X-FORWARDED-FOR", "1.1.1.1")
            .build()
            .get()
            .uri(endpoint)
            .exchange()
            .expectStatus().isOk
            .expectHeader().valueEquals("X-Rate-Limit-Remaining", "0")
    
        WebTestClient
            .bindToApplicationContext(context)
            .configureClient()
            .defaultHeader("X-FORWARDED-FOR", "1.1.1.2")
            .build()
            .get()
            .uri(endpoint)
            .exchange()
            .expectStatus().isOk
            .expectHeader().valueEquals("X-Rate-Limit-Remaining", "0")
    
        WebTestClient
            .bindToApplicationContext(context)
            .configureClient()
            .defaultHeader("X-FORWARDED-FOR", "1.1.1.1")
            .build()
            .get()
            .uri(endpoint)
            .exchange()
            .expectStatus().isEqualTo(HttpStatus.TOO_MANY_REQUESTS)
            .expectBody().jsonPath("error", "Too many requests!")
    
        // assert
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-01
      • 2018-08-24
      • 2020-08-26
      • 2020-10-24
      • 2019-06-08
      • 1970-01-01
      • 2020-05-04
      相关资源
      最近更新 更多