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>;
|
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.
|
* 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 { FolderDTO } from 'app/types';
|
||||||
import { coreModule } from 'app/core/core_module';
|
import { coreModule } from 'app/core/core_module';
|
||||||
import { ContextSrv, contextSrv } from './context_srv';
|
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 { isDataQuery, isLocalUrl } from '../utils/query';
|
||||||
import { FetchQueue } from './FetchQueue';
|
import { FetchQueue } from './FetchQueue';
|
||||||
import { ResponseQueue } from './ResponseQueue';
|
import { ResponseQueue } from './ResponseQueue';
|
||||||
@@ -175,15 +175,8 @@ export class BackendSrv implements BackendService {
|
|||||||
return this.dependencies.fromFetch(url, init).pipe(
|
return this.dependencies.fromFetch(url, init).pipe(
|
||||||
mergeMap(async response => {
|
mergeMap(async response => {
|
||||||
const { status, statusText, ok, headers, url, type, redirected } = 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> = {
|
const fetchResponse: FetchResponse<T> = {
|
||||||
status,
|
status,
|
||||||
statusText,
|
statusText,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
parseCredentials,
|
parseCredentials,
|
||||||
parseHeaders,
|
parseHeaders,
|
||||||
parseInitFromOptions,
|
parseInitFromOptions,
|
||||||
|
parseResponseBody,
|
||||||
parseUrlFromOptions,
|
parseUrlFromOptions,
|
||||||
} from './fetch';
|
} 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);
|
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 {
|
export function serializeParams(data: Record<string, any>): string {
|
||||||
return Object.keys(data)
|
return Object.keys(data)
|
||||||
.map(key => {
|
.map(key => {
|
||||||
|
|||||||
Reference in New Issue
Block a user