Fix agent nodes proxy response headers

This commit is contained in:
Haitao Pan 2026-04-11 11:59:44 +08:00
parent 3d36f8dd30
commit fe81be2874
3 changed files with 63 additions and 2 deletions

52
src/lib/apiProxy.test.ts Normal file
View File

@ -0,0 +1,52 @@
// @vitest-environment node
import { afterEach, describe, expect, it, vi } from 'vitest'
import { NextRequest } from 'next/server'
import { proxyRequestToUpstream } from './apiProxy'
describe('proxyRequestToUpstream', () => {
afterEach(() => {
vi.unstubAllGlobals()
})
it('strips stale encoding headers when the upstream body is already decoded', async () => {
const fetchMock = vi.fn().mockResolvedValue(
new Response(JSON.stringify([{ name: 'JP', address: 'jp-xhttp.svc.plus' }]), {
status: 200,
headers: {
'Content-Encoding': 'gzip',
'Content-Length': '405',
'Content-Type': 'application/json; charset=utf-8',
},
}),
)
vi.stubGlobal('fetch', fetchMock)
const response = await proxyRequestToUpstream(
new NextRequest('https://console.svc.plus/api/agent/nodes', {
headers: {
host: 'console.svc.plus',
},
}),
{
upstreamBaseUrl: 'https://accounts.svc.plus',
upstreamPathPrefix: '/api/agent',
},
)
expect(fetchMock).toHaveBeenCalledWith(
'https://accounts.svc.plus/api/agent/nodes',
expect.objectContaining({
cache: 'no-store',
method: 'GET',
redirect: 'manual',
}),
)
expect(response.status).toBe(200)
expect(response.headers.get('content-encoding')).toBeNull()
expect(response.headers.get('content-length')).toBeNull()
expect(response.headers.get('content-type')).toBe('application/json; charset=utf-8')
await expect(response.json()).resolves.toEqual([{ name: 'JP', address: 'jp-xhttp.svc.plus' }])
})
})

View File

@ -14,6 +14,14 @@ const DEFAULT_FORWARD_HEADERS = [
'x-trace-id',
] as const
const RESPONSE_HEADERS_TO_STRIP = new Set([
'connection',
'content-encoding',
'content-length',
'keep-alive',
'transfer-encoding',
])
const BODYLESS_METHODS = new Set(['GET', 'HEAD'])
type ProxyOptions = {
@ -107,7 +115,8 @@ export async function proxyRequestToUpstream(request: NextRequest, options: Prox
const responseHeaders = new Headers()
upstreamResponse.headers.forEach((value, key) => {
if (key.toLowerCase() === 'set-cookie') {
const normalizedKey = key.toLowerCase()
if (normalizedKey === 'set-cookie' || RESPONSE_HEADERS_TO_STRIP.has(normalizedKey)) {
return
}
responseHeaders.set(key, value)

View File

@ -20,7 +20,7 @@ describe('fetchAgentNodes', () => {
await expect(fetchAgentNodes()).resolves.toEqual([{ name: 'JP', address: 'jp-xhttp.svc.plus' }])
expect(fetchMock).toHaveBeenCalledTimes(1)
expect(fetchMock).toHaveBeenCalledWith(
'/api/agent-server/v1/nodes',
'/api/auth/sync/config?since_version=0',
expect.objectContaining({
cache: 'no-store',
credentials: 'include',