Skip to content

Commit 151c777

Browse files
airjp73Aaron Pettengillphryneas
authored
Handle empty json response (#91)
Co-authored-by: Aaron Pettengill <[email protected]> Co-authored-by: Lenz Weber <[email protected]>
1 parent b221a12 commit 151c777

File tree

3 files changed

+36
-6
lines changed

3 files changed

+36
-6
lines changed

src/fetchBaseQuery.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,35 @@ import { joinUrls } from './utils';
22
import { isPlainObject } from '@reduxjs/toolkit';
33
import { BaseQueryFn } from './apiTypes';
44

5+
export type ResponseHandler = 'json' | 'text' | ((response: Response) => Promise<any>);
6+
57
export interface FetchArgs extends RequestInit {
68
url: string;
79
params?: Record<string, any>;
810
body?: any;
9-
responseHandler?: 'json' | 'text' | ((response: Response) => Promise<any>);
11+
responseHandler?: ResponseHandler;
1012
validateStatus?: (response: Response, body: any) => boolean;
1113
}
1214

1315
const defaultValidateStatus = (response: Response) => response.status >= 200 && response.status <= 299;
1416

1517
const isJsonContentType = (headers: Headers) => headers.get('content-type')?.trim()?.startsWith('application/json');
1618

19+
const handleResponse = async (response: Response, responseHandler: ResponseHandler) => {
20+
if (typeof responseHandler === 'function') {
21+
return responseHandler(response);
22+
}
23+
24+
if (responseHandler === 'text') {
25+
return response.text();
26+
}
27+
28+
if (responseHandler === 'json') {
29+
const text = await response.text();
30+
return text.length ? JSON.parse(text) : undefined;
31+
}
32+
};
33+
1734
export interface FetchBaseQueryError {
1835
status: number;
1936
data: unknown;
@@ -65,11 +82,7 @@ export function fetchBaseQuery({
6582
url = joinUrls(baseUrl, url);
6683

6784
const response = await fetch(url, config);
68-
69-
const resultData =
70-
typeof responseHandler === 'function'
71-
? await responseHandler(response)
72-
: await response[responseHandler || 'text']();
85+
const resultData = await handleResponse(response, responseHandler);
7386

7487
return validateStatus(response, resultData)
7588
? { data: resultData }

test/fetchBaseQuery.test.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,22 @@ describe('fetchBaseQuery', () => {
8989
expect(res.data).toEqual({ value: 'success' });
9090
});
9191

92+
it('should return undefined for a simple GET request when the response is empty', async () => {
93+
const req = baseQuery(
94+
'/empty',
95+
{
96+
signal: undefined,
97+
dispatch: storeRef.store.dispatch,
98+
getState: storeRef.store.getState,
99+
},
100+
{}
101+
);
102+
expect(req).toBeInstanceOf(Promise);
103+
const res = await req;
104+
expect(res).toBeInstanceOf(Object);
105+
expect(res.data).toBeUndefined();
106+
});
107+
92108
it('should return an error and status for error responses', async () => {
93109
const req = baseQuery(
94110
'/error',

test/mocks/server.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { rest } from 'msw';
77
export const server = setupServer(
88
rest.get('http://example.com/success', (_, res, ctx) => res(ctx.json({ value: 'success' }))),
99
rest.post('http://example.com/success', (_, res, ctx) => res(ctx.json({ value: 'success' }))),
10+
rest.get('http://example.com/empty', (_, res, ctx) => res(ctx.body(''))),
1011
rest.get('http://example.com/error', (_, res, ctx) => res.once(ctx.status(500), ctx.json({ value: 'error' }))),
1112
rest.post('http://example.com/error', (_, res, ctx) => res.once(ctx.status(500), ctx.json({ value: 'error' }))),
1213
rest.get('http://example.com/nonstandard-error', (_, res, ctx) =>

0 commit comments

Comments
 (0)