mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
BackendSrv: support binary responseType like $http did (#29004)
This commit is contained in:
@@ -61,6 +61,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.
|
||||
*/
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
Reference in New Issue
Block a user