Commit d85d547a by Ryan McKinley Committed by GitHub

BackendSrv: support binary responseType like $http did (#29004)

parent 18956260
......@@ -62,6 +62,15 @@ export type BackendSrvRequest = {
params?: Record<string, any>;
/**
* Define how the response object should be parsed. See:
*
* https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data
*
* By default values are json parsed from text
*/
responseType?: 'json' | 'text' | 'arraybuffer' | 'blob';
/**
* The credentials read-only property of the Request interface indicates whether the user agent should send cookies from the other domain in the case of cross-origin requests.
*/
credentials?: RequestCredentials;
......
......@@ -11,7 +11,7 @@ import { DashboardSearchHit } from 'app/features/search/types';
import { FolderDTO } from 'app/types';
import { coreModule } from 'app/core/core_module';
import { ContextSrv, contextSrv } from './context_srv';
import { parseInitFromOptions, parseUrlFromOptions } from '../utils/fetch';
import { parseInitFromOptions, parseResponseBody, parseUrlFromOptions } from '../utils/fetch';
import { isDataQuery, isLocalUrl } from '../utils/query';
import { FetchQueue } from './FetchQueue';
import { ResponseQueue } from './ResponseQueue';
......@@ -175,15 +175,8 @@ export class BackendSrv implements BackendService {
return this.dependencies.fromFetch(url, init).pipe(
mergeMap(async response => {
const { status, statusText, ok, headers, url, type, redirected } = response;
const textData = await response.text(); // this could be just a string, prometheus requests for instance
let data: T;
try {
data = JSON.parse(textData); // majority of the requests this will be something that can be parsed
} catch {
data = textData as any;
}
const data = await parseResponseBody<T>(response, options.responseType);
const fetchResponse: FetchResponse<T> = {
status,
statusText,
......
......@@ -5,6 +5,7 @@ import {
parseCredentials,
parseHeaders,
parseInitFromOptions,
parseResponseBody,
parseUrlFromOptions,
} from './fetch';
......@@ -127,3 +128,48 @@ describe('parseCredentials', () => {
}
);
});
describe('parseResponseBody', () => {
const rsp = ({} as unknown) as Response;
it('parses json', async () => {
const value = { hello: 'world' };
const body = await parseResponseBody(
{
...rsp,
json: jest.fn().mockImplementationOnce(() => value),
},
'json'
);
expect(body).toEqual(value);
});
it('parses text', async () => {
const value = 'RAW TEXT';
const body = await parseResponseBody(
{
...rsp,
text: jest.fn().mockImplementationOnce(() => value),
},
'text'
);
expect(body).toEqual(value);
});
it('undefined text', async () => {
const value = 'RAW TEXT';
const body = await parseResponseBody({
...rsp,
text: jest.fn().mockImplementationOnce(() => value),
});
expect(body).toEqual(value);
});
it('undefined as parsed json', async () => {
const value = { hello: 'world' };
const body = await parseResponseBody({
...rsp,
text: jest.fn().mockImplementationOnce(() => JSON.stringify(value)),
});
expect(body).toEqual(value);
});
});
......@@ -91,6 +91,33 @@ export const parseBody = (options: BackendSrvRequest, isAppJson: boolean) => {
return isAppJson ? JSON.stringify(options.data) : new URLSearchParams(options.data);
};
export async function parseResponseBody<T>(
response: Response,
responseType?: 'json' | 'text' | 'arraybuffer' | 'blob'
): Promise<T> {
if (responseType) {
switch (responseType) {
case 'arraybuffer':
return response.arrayBuffer() as any;
case 'blob':
return response.blob() as any;
case 'json':
return response.json();
case 'text':
return response.text() as any;
}
}
const textData = await response.text(); // this could be just a string, prometheus requests for instance
try {
return JSON.parse(textData); // majority of the requests this will be something that can be parsed
} catch {}
return textData as any;
}
export function serializeParams(data: Record<string, any>): string {
return Object.keys(data)
.map(key => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment