fix: prevent SSE stream corruption by requesting identity encoding

Add 'accept-encoding: identity' to upstream request headers to prevent
Cloudflare/Anthropic CDN from returning gzip-compressed SSE responses.

When the upstream returns gzip data without a Content-Encoding header
(observed with some CDN edge configurations), the stream handler's
chunk.toString() call decodes raw gzip bytes as UTF-8, replacing any
byte >= 0x80 that isn't valid UTF-8 with U+FFFD (ef bf bd). This
silently corrupts the entire SSE stream.

Explicitly requesting identity encoding is the simplest and most
reliable fix — it prevents compression at the source rather than
trying to detect and decompress it after the fact.

Closes #1030
This commit is contained in:
atian8179
2026-03-01 15:19:38 +08:00
parent 0871101f27
commit 4d5ea4e0bc

View File

@@ -1494,11 +1494,16 @@ class ClaudeRelayService {
const contentLength = Buffer.byteLength(bodyString, 'utf8')
// 构建最终请求头包含认证、版本、User-Agent、Beta 等)
// Force identity encoding to prevent upstream (Cloudflare) from returning
// gzip-compressed responses without a Content-Encoding header, which causes
// binary data to be silently corrupted by UTF-8 text decoding in the stream
// handler. See: https://github.com/Wei-Shaw/claude-relay-service/issues/1030
const headers = {
host: 'api.anthropic.com',
connection: 'keep-alive',
'content-type': 'application/json',
'content-length': String(contentLength),
'accept-encoding': 'identity',
authorization: `Bearer ${accessToken}`,
'anthropic-version': this.apiVersion,
...finalHeaders