spring-cloud / spring-cloud/spring-cloud-gateway

LocalResponseCache fails to retrieve if RemoveRequestHeader is used

Open
#3,152 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

waiting-for-triage
Dominant language
Java
Stars
4.9k
Forks
3.5k
Avg merge
20h 57m
Merged PRs (30d)
8

Description

I am encountering an issue while utilizing the LocalResponseCache filter.

The issue is about the execution order. Once the response is cached, subsequent requests made through gateway retrieve responses from the cache, cause gateway to bypass previous filters such as CheckIfRouteEnabled, AuthenticateRequest, and Authorize.

This behavior is undesirable for my use case, where I am generating a policy inquiry data and placing it in the gateway attributes within the Authenticate filter code. This data is then used to execute policies when filter needs it, such as Authorize and DropFieldsForFindEntityById to determine who can call and see what. As this data couldn't be prepared when Authenticate filter is skipped, DropFieldsForFindEntityById filter is failing.

Another issue is when I remove the Authorization header before forwarding the request to the downstream service. This causes the key calculated to put to the cache to differ from the key calculated when getting the data from the cache.

The expected behavior is to execute all filters in the specified order before reaching the LocalResponseCache. If the request is cached, I would expect filters CheckIfRouteEnabled, AuthenticateRequest, and Authorize to be executed and continue with ApplyFieldsetConfig and DropFieldsForFindEntityById as if the response were obtained from the backend. If the request is not cached, again the previous filters should be executed, then response should be cached, and the execution should proceed with ApplyFieldsetConfig and DropFieldsForFindEntityById filters.

Here is the route configuration I am using:

- id: findEntityByIdByKindPath
  uri: ${app.backend.protocol}://${app.backend.host}:${app.backend.port}
  predicates:
    - Path=${app.inbound.baseUri}{kindPath}/{recordId}
    - Method=GET
  filters:
    - name: CheckIfRouteEnabled
    - RewritePath=${app.inbound.baseUri}(?<kindPath>/?.*)\/(?<recordId>.*), ${app.backend.baseUri}generic-entities/${recordId}
    - name: AuthenticateRequest
    - name: RequestRateLimiter
      args:
        redis-rate-limiter:
          replenishRate: 10
          burstCapacity: 20
    - name: AuthorizeRequest
      args:
        policyName: /policies/auth/routes/findEntityById/policy
    - RemoveRequestHeader=Authorization
    - LocalResponseCache=${app.caching.timeToLive},${app.caching.size}
    - name: ApplyFieldsetConfig
    - name: DropFieldsForFindEntityById
      args:
        policyName: /policies/fields/genericentities/policy

Execution order of the ApplyFieldsetConfig and DropFieldsForFindEntityById are:

NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER - 10

Other filters does not have given order in the code.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the route configuration with LocalResponseCache, RemoveRequestHeader=Authorization, and the listed authentication and authorization filters. Read the LocalResponseCache behavior alongside NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER and the ApplyFieldsetConfig and DropFieldsForFindEntityById entry points. Done means ordered filters still run for cached and uncached requests, and cache-key calculation remains consistent after the authorization header is removed.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring, spring-boot
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.