From cd6809685f3fd296f5ef4f24b32c9d508938f02a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Mon, 10 Feb 2020 06:29:52 +0100 Subject: [PATCH] BackendSrv: Returns correct error when a request is cancelled (#21992) Fixes #21991 --- public/app/core/services/backend_srv.ts | 19 +++++----- public/app/core/specs/backend_srv.test.ts | 43 +++++++++-------------- 2 files changed, 26 insertions(+), 36 deletions(-) diff --git a/public/app/core/services/backend_srv.ts b/public/app/core/services/backend_srv.ts index b7a92d9abbe..73f6e24f028 100644 --- a/public/app/core/services/backend_srv.ts +++ b/public/app/core/services/backend_srv.ts @@ -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(); } diff --git a/public/app/core/specs/backend_srv.test.ts b/public/app/core/specs/backend_srv.test.ts index 7c22c0021f1..508556ffd17 100644 --- a/public/app/core/specs/backend_srv.test.ts +++ b/public/app/core/specs/backend_srv.test.ts @@ -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({