apache / apache/shenyu

[BUG] Cache plugin loses response status and headers on cache hit

Open
#6,505 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
8.8k
Forks
3.1k
Avg merge
7d 1h
Merged PRs (30d)
85

Description

### Search before asking

- [x] I had searched in the [issues](https://github.com/apache/shenyu/issues) and found no similar issues.

### Apache ShenYu Component

shenyu-plugin

### What happened

`CachePlugin` stores only the response body and content type:

```java
cache.cacheData(CacheUtils.dataKey(this.exchange), bodyBytes,
this.cacheRuleHandle.getTimeoutSeconds()).subscribeOn(Schedulers.boundedElastic()).subscribe();
cache.cacheContentType(CacheUtils.contentTypeKey(this.exchange), contentType, this.cacheRuleHandle.getTimeoutSeconds());
```

On a cache hit it only restores those two values:

```java
byte[] bytes = dataFlg.get().getT1();
byte[] contentTypeBytes = dataFlg.get().getT2();
cache.setContentType(exchange, contentTypeBytes);
return exchange.getResponse().writeWith(Mono.just(exchange.getResponse().bufferFactory().wrap(bytes))
.doOnNext(data -> exchange.getResponse().getHeaders().setContentLength(data.readableByteCount())));
```

The upstream HTTP status code and other response headers are not cached or replayed. This changes response semantics after the first request. For example:

- an upstream `404`/`500` response body can be replayed as a default gateway `200` on cache hit;
- a cached `302` loses the `Location` header;
- `Set-Cookie`, `Cache-Control`, and other important headers are dropped on cache hit.

### Expected behavior

A cached HTTP response should preserve the response semantics that ShenYu returned when the entry was stored. At minimum, the cache entry should include and restore the HTTP status code and relevant response headers, or the cache plugin should explicitly avoid caching responses whose status/headers cannot be safely replayed.

### How to reproduce

1. Enable the cache plugin for a route.
2. Let the upstream return a non-200 response, or a redirect response such as:

```text
HTTP/1.1 302 Found
Location: /new-location
Content-Type: text/plain
```

3. Send the first request so the cache entry is created.
4. Send the same request again.
5. The cache hit path returns only cached body/content-type and does not restore the original status or headers.

### Debug logs

_No response_

### Environment

Current `master` branch.

### Are you willing to submit a PR?

- [ ] Yes I am willing to submit a PR!

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by tracing CachePlugin's cache-write and cache-hit paths, including the CacheUtils keys and cacheContentType calls shown in the report. Reproduce a cached 302 or error response, then verify that a cache hit preserves the original status and relevant headers, or that unsafe responses are not cached.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.