BackendSrv: Returns correct error when a request is cancelled (#21992)

Fixes #21991
This commit is contained in:
Hugo Häggmark 2020-02-10 06:29:52 +01:00 committed by GitHub
parent 31101d54a4
commit cd6809685f
2 changed files with 26 additions and 36 deletions

View File

@ -1,6 +1,6 @@
import omitBy from 'lodash/omitBy';
import { from, merge, MonoTypeOperatorFunction, Observable, Subject, throwError } from 'rxjs';
import { catchError, filter, map, mergeMap, retryWhen, share, takeUntil, tap } from 'rxjs/operators';
import { catchError, filter, map, mergeMap, retryWhen, share, takeUntil, tap, throwIfEmpty } from 'rxjs/operators';
import { fromFetch } from 'rxjs/fetch';
import { BackendSrv as BackendService, BackendSrvRequest } from '@grafana/runtime';
import { AppEvents } from '@grafana/data';
@ -214,13 +214,6 @@ export class BackendSrv implements BackendService {
return merge(successStream, failureStream)
.pipe(
catchError((err: ErrorResponse) => {
if (err.status === this.HTTP_REQUEST_CANCELED) {
return throwError({
err,
cancelled: true,
});
}
// populate error obj on Internal Error
if (typeof err.data === 'string' && err.status === 500) {
err.data = {
@ -253,7 +246,15 @@ export class BackendSrv implements BackendService {
return cancelRequest;
})
)
)
),
// when a request is cancelled by takeUntil it will complete without emitting anything
// throwIfEmpty will then throw an error with cancelled set to true
throwIfEmpty(() => ({
cancelled: true,
status: this.HTTP_REQUEST_CANCELED,
statusText: 'Request was aborted',
request: { url: parseUrlFromOptions(options), ...parseInitFromOptions(options) },
}))
)
.toPromise();
}

View File

@ -416,8 +416,22 @@ describe('backendSrv', () => {
},
});
const slowResponse = await slowRequest;
expect(slowResponse).toEqual(undefined);
await slowRequest.catch(error => {
expect(error).toEqual({
cancelled: true,
status: -1,
statusText: 'Request was aborted',
request: {
url,
method: 'GET',
body: undefined,
headers: {
'Content-Type': 'application/json',
Accept: 'application/json, text/plain, */*',
},
},
});
});
expect(unsubscribe).toHaveBeenCalledTimes(1);
});
});
@ -480,31 +494,6 @@ describe('backendSrv', () => {
});
});
describe('when making a HTTP_REQUEST_CANCELED call', () => {
it('then it should throw cancelled error', async () => {
const { backendSrv, appEventsMock, logoutMock, expectDataSourceRequestCallChain } = getTestContext({
ok: false,
status: -1,
statusText: 'HTTP_REQUEST_CANCELED',
data: { message: 'HTTP_REQUEST_CANCELED' },
});
const url = '/api/dashboard/';
await backendSrv.datasourceRequest({ url, method: 'GET' }).catch(error => {
expect(error).toEqual({
err: {
status: -1,
statusText: 'HTTP_REQUEST_CANCELED',
data: { message: 'HTTP_REQUEST_CANCELED' },
},
cancelled: true,
});
expect(appEventsMock.emit).not.toHaveBeenCalled();
expect(logoutMock).not.toHaveBeenCalled();
expectDataSourceRequestCallChain({ url, method: 'GET' });
});
});
});
describe('when making an Internal Error call', () => {
it('then it should throw cancelled error', async () => {
const { backendSrv, appEventsMock, logoutMock, expectDataSourceRequestCallChain } = getTestContext({