Skip to content

Commit f4ced9d

Browse files
committed
Add handling for accept headers
1 parent dc66c76 commit f4ced9d

File tree

3 files changed

+132
-2
lines changed

3 files changed

+132
-2
lines changed

packages/toolkit/src/query/fetchBaseQuery.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,16 @@ export function fetchBaseQuery({
279279
config.body = JSON.stringify(config.body, jsonReplacer)
280280
}
281281

282+
// Set Accept header based on responseHandler if not already set
283+
if (!config.headers.has('accept')) {
284+
if (responseHandler === 'json') {
285+
config.headers.set('accept', 'application/json')
286+
} else if (responseHandler === 'text') {
287+
config.headers.set('accept', 'text/plain, text/html, */*')
288+
}
289+
// For 'content-type' responseHandler, don't set Accept (let server decide)
290+
}
291+
282292
if (params) {
283293
const divider = ~url.indexOf('?') ? '&' : '?'
284294
const query = paramsSerializer

packages/toolkit/src/query/tests/createApi.test.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,7 @@ describe('additional transformResponse behaviors', () => {
712712
meta: {
713713
request: {
714714
headers: {
715+
accept: 'application/json',
715716
'content-type': 'application/json',
716717
},
717718
},
@@ -733,7 +734,9 @@ describe('additional transformResponse behaviors', () => {
733734
value: 'success',
734735
meta: {
735736
request: {
736-
headers: {},
737+
headers: {
738+
accept: 'application/json',
739+
},
737740
},
738741
response: {
739742
headers: {

packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx

Lines changed: 118 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { createSlice } from '@reduxjs/toolkit'
2-
import { createApi, FetchArgs, fetchBaseQuery } from '@reduxjs/toolkit/query'
2+
import type { FetchArgs } from '@reduxjs/toolkit/query'
3+
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'
34
import { headersToObject } from 'headers-polyfill'
45
import { HttpResponse, delay, http } from 'msw'
56
// @ts-ignore
@@ -1255,6 +1256,122 @@ describe('FormData', () => {
12551256
})
12561257
})
12571258

1259+
describe('Accept header handling', () => {
1260+
test('sets Accept header to application/json for json responseHandler', async () => {
1261+
let request: any
1262+
;({ data: request } = await baseQuery(
1263+
{ url: '/echo', responseHandler: 'json' },
1264+
commonBaseQueryApi,
1265+
{},
1266+
))
1267+
1268+
expect(request.headers['accept']).toBe('application/json')
1269+
})
1270+
1271+
test('sets Accept header to application/json by default (json is default responseHandler)', async () => {
1272+
let request: any
1273+
;({ data: request } = await baseQuery(
1274+
{ url: '/echo' },
1275+
commonBaseQueryApi,
1276+
{},
1277+
))
1278+
1279+
expect(request.headers['accept']).toBe('application/json')
1280+
})
1281+
1282+
test('sets Accept header for text responseHandler', async () => {
1283+
// Create a baseQuery with text as the global responseHandler
1284+
const textBaseQuery = fetchBaseQuery({
1285+
baseUrl,
1286+
fetchFn: fetchFn as any,
1287+
responseHandler: 'text',
1288+
})
1289+
1290+
let request: any
1291+
// Override to json just for this test so we can inspect the echoed request object
1292+
;({ data: request } = await textBaseQuery(
1293+
{ url: '/echo', responseHandler: 'json' },
1294+
commonBaseQueryApi,
1295+
{},
1296+
))
1297+
1298+
// The endpoint-level 'json' responseHandler overrides the global 'text',
1299+
// so the Accept header should be application/json
1300+
expect(request.headers['accept']).toBe('application/json')
1301+
})
1302+
1303+
test('does not override explicit Accept header from endpoint', async () => {
1304+
let request: any
1305+
;({ data: request } = await baseQuery(
1306+
{
1307+
url: '/echo',
1308+
responseHandler: 'json',
1309+
headers: { Accept: 'application/xml' },
1310+
},
1311+
commonBaseQueryApi,
1312+
{},
1313+
))
1314+
1315+
expect(request.headers['accept']).toBe('application/xml')
1316+
})
1317+
1318+
test('does not override Accept header set in prepareHeaders', async () => {
1319+
const customBaseQuery = fetchBaseQuery({
1320+
baseUrl,
1321+
fetchFn: fetchFn as any,
1322+
prepareHeaders: (headers) => {
1323+
headers.set('Accept', 'application/vnd.api+json')
1324+
return headers
1325+
},
1326+
})
1327+
1328+
let request: any
1329+
;({ data: request } = await customBaseQuery(
1330+
{ url: '/echo', responseHandler: 'json' },
1331+
commonBaseQueryApi,
1332+
{},
1333+
))
1334+
1335+
expect(request.headers['accept']).toBe('application/vnd.api+json')
1336+
})
1337+
1338+
test('does not set Accept header for content-type responseHandler', async () => {
1339+
let request: any
1340+
;({ data: request } = await baseQuery(
1341+
{ url: '/echo', responseHandler: 'content-type' },
1342+
commonBaseQueryApi,
1343+
{},
1344+
))
1345+
1346+
// Should either not have accept header or have a permissive one
1347+
// content-type handler adapts to whatever server sends
1348+
const acceptHeader = request.headers['accept']
1349+
if (acceptHeader) {
1350+
expect(acceptHeader).toMatch(/\*\/\*/)
1351+
}
1352+
})
1353+
1354+
test('respects global responseHandler for Accept header', async () => {
1355+
const textBaseQuery = fetchBaseQuery({
1356+
baseUrl,
1357+
fetchFn: fetchFn as any,
1358+
responseHandler: 'text',
1359+
})
1360+
1361+
let request: any
1362+
// Override to json just for this test so we can inspect the echoed request object
1363+
;({ data: request } = await textBaseQuery(
1364+
{ url: '/echo', responseHandler: 'json' },
1365+
commonBaseQueryApi,
1366+
{},
1367+
))
1368+
1369+
// The endpoint-level 'json' responseHandler overrides the global 'text',
1370+
// so the Accept header should be application/json (proving endpoint-level takes precedence)
1371+
expect(request.headers['accept']).toBe('application/json')
1372+
})
1373+
})
1374+
12581375
describe('still throws on completely unexpected errors', () => {
12591376
test('', async () => {
12601377
const error = new Error('some unexpected error')

0 commit comments

Comments
 (0)