fix(client): merge function headers with per-request headers (#5092)

This commit is contained in:
Yusuke Wada
2026-07-07 18:10:45 +09:00
committed by GitHub
parent 626b185d0e
commit f9992096de
2 changed files with 70 additions and 1 deletions
+60
View File
@@ -1201,6 +1201,7 @@ describe('Dynamic headers', () => {
const route = app.post('/posts', (c) => {
return c.json({
requestDynamic: 'dummy',
requestHono: 'dummy',
})
})
@@ -1209,8 +1210,10 @@ describe('Dynamic headers', () => {
const server = setupServer(
http.post('http://localhost/posts', async ({ request }) => {
const requestDynamic = request.headers.get('x-dynamic')
const requestHono = request.headers.get('x-hono')
const payload = {
requestDynamic,
requestHono,
}
return HttpResponse.json(payload)
})
@@ -1245,6 +1248,63 @@ describe('Dynamic headers', () => {
const data = await res.json()
expect(data.requestDynamic).toEqual('two')
})
it('Should merge function headers with per-request object headers', async () => {
const clientWithFn = hc<AppType>('http://localhost', {
headers: async () => ({ 'x-hono': 'hono' }),
})
const res = await clientWithFn.posts.$post({}, { headers: { 'x-dynamic': 'request' } })
expect(res.ok).toBe(true)
const data = await res.json()
expect(data.requestHono).toEqual('hono')
expect(data.requestDynamic).toEqual('request')
})
it('Should merge function headers with per-request function headers', async () => {
const clientWithFn = hc<AppType>('http://localhost', {
headers: () => ({ 'x-hono': 'hono' }),
})
const res = await clientWithFn.posts.$post(
{},
{ headers: async () => ({ 'x-dynamic': 'request' }) }
)
expect(res.ok).toBe(true)
const data = await res.json()
expect(data.requestHono).toEqual('hono')
expect(data.requestDynamic).toEqual('request')
})
it('Should merge object headers with per-request function headers', async () => {
const clientWithObject = hc<AppType>('http://localhost', {
headers: { 'x-hono': 'hono' },
})
const res = await clientWithObject.posts.$post(
{},
{ headers: async () => ({ 'x-dynamic': 'request' }) }
)
expect(res.ok).toBe(true)
const data = await res.json()
expect(data.requestHono).toEqual('hono')
expect(data.requestDynamic).toEqual('request')
})
it('Should prioritize per-request headers when the keys conflict', async () => {
const clientWithFn = hc<AppType>('http://localhost', {
headers: async () => ({ 'x-hono': 'client' }),
})
const res = await clientWithFn.posts.$post({}, { headers: { 'x-hono': 'request' } })
expect(res.ok).toBe(true)
const data = await res.json()
expect(data.requestHono).toEqual('request')
})
})
describe('RequestInit work as expected', () => {
+10 -1
View File
@@ -216,7 +216,16 @@ export const hc = <T extends Hono<any, any, any>, Prefix extends string = string
})
if (method) {
options ??= {}
const args = deepMerge<ClientRequestOptions>(options, { ...opts.args[1] })
const reqOptions: ClientRequestOptions = { ...opts.args[1] }
const baseHeaders = options.headers
const reqHeaders = reqOptions.headers
if (baseHeaders && reqHeaders) {
reqOptions.headers = async () => ({
...(typeof baseHeaders === 'function' ? await baseHeaders() : baseHeaders),
...(typeof reqHeaders === 'function' ? await reqHeaders() : reqHeaders),
})
}
const args = deepMerge<ClientRequestOptions>(options, reqOptions)
return req.fetch(opts.args[0], args)
}
return req