Skip to content

Commit cdc55e7

Browse files
msutkowskiShaunDychkophryneas
authored
Add isJsonContentType predicate to fetchBaseQuery (#2331)
Co-authored-by: Shaun Dychko <[email protected]> Co-authored-by: Lenz Weber-Tronic <[email protected]>
1 parent 8bdb80e commit cdc55e7

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

packages/toolkit/src/query/fetchBaseQuery.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ const defaultFetchFn: typeof fetch = (...args) => fetch(...args)
3737
const defaultValidateStatus = (response: Response) =>
3838
response.status >= 200 && response.status <= 299
3939

40-
const isJsonContentType = (headers: Headers) =>
41-
headers.get('content-type')?.trim()?.startsWith('application/json')
40+
const defaultIsJsonContentType = (headers: Headers) =>
41+
/*applicat*//ion\/(vnd\.api\+)?json/.test(headers.get('content-type') || '')
4242

4343
const handleResponse = async (
4444
response: Response,
@@ -123,6 +123,15 @@ export type FetchBaseQueryArgs = {
123123
init?: RequestInit | undefined
124124
) => Promise<Response>
125125
paramsSerializer?: (params: Record<string, any>) => string
126+
/**
127+
* By default, we only check for 'application/json' and 'application/vnd.api+json' as the content-types for json. If you need to support another format, you can pass
128+
* in a predicate function for your given api to get the same automatic stringifying behavior
129+
* @example
130+
* ```ts
131+
* const isJsonContentType = (headers: Headers) => ["application/vnd.api+json", "application/json", "application/vnd.hal+json"].includes(headers.get("content-type")?.trim());
132+
* ```
133+
*/
134+
isJsonContentType?: (headers: Headers) => boolean
126135
} & RequestInit
127136

128137
export type FetchBaseQueryMeta = { request: Request; response?: Response }
@@ -162,12 +171,17 @@ export type FetchBaseQueryMeta = { request: Request; response?: Response }
162171
*
163172
* @param {(params: Record<string, unknown>) => string} paramsSerializer
164173
* An optional function that can be used to stringify querystring parameters.
174+
*
175+
* @param {(headers: Headers) => boolean} isJsonContentType
176+
* An optional predicate function to determine if `JSON.stringify()` should be called on the `body` arg of `FetchArgs`
177+
165178
*/
166179
export function fetchBaseQuery({
167180
baseUrl,
168181
prepareHeaders = (x) => x,
169182
fetchFn = defaultFetchFn,
170183
paramsSerializer,
184+
isJsonContentType = defaultIsJsonContentType,
171185
...baseFetchOptions
172186
}: FetchBaseQueryArgs = {}): BaseQueryFn<
173187
string | FetchArgs,

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,34 @@ describe('fetchBaseQuery', () => {
399399
`${baseUrl}/echo?someArray[]=a&someArray[]=b&someArray[]=c`
400400
)
401401
})
402+
403+
it('should supports a custom isJsonContentType function', async () => {
404+
const testBody = {
405+
i_should_be_stringified: true,
406+
}
407+
const baseQuery = fetchBaseQuery({
408+
baseUrl,
409+
fetchFn: fetchFn as any,
410+
isJsonContentType: (headers) =>
411+
['application/vnd.api+json', 'application/json', 'application/vnd.hal+json'].includes(
412+
headers.get('content-type') ?? ''
413+
),
414+
})
415+
416+
let request: any
417+
;({ data: request } = await baseQuery(
418+
{
419+
url: '/echo',
420+
method: 'POST',
421+
body: testBody,
422+
headers: { 'content-type': 'application/vnd.hal+json' },
423+
},
424+
commonBaseQueryApi,
425+
{}
426+
))
427+
428+
expect(request.body).toMatchObject(testBody)
429+
})
402430
})
403431

404432
describe('validateStatus', () => {

0 commit comments

Comments
 (0)