Skip to content

Commit da62f57

Browse files
authored
release(required): network error has not been properly detected (#13935)
* fix(core): retry is not applied on network error * fix(auth): wrongly clear tokens on network error when refresh tokens * chore(aws-amplify): bump list bundle size limits
1 parent 3f8451c commit da62f57

File tree

5 files changed

+70
-4
lines changed

5 files changed

+70
-4
lines changed

packages/auth/__tests__/providers/cognito/tokenProvider/tokenOrchestrator.test.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4+
import {
5+
AmplifyError,
6+
AmplifyErrorCode,
7+
} from '@aws-amplify/core/internals/utils';
8+
49
import { tokenOrchestrator } from '../../../../src/providers/cognito/tokenProvider';
510
import { CognitoAuthTokens } from '../../../../src/providers/cognito/tokenProvider/types';
611
import { oAuthStore } from '../../../../src/providers/cognito/utils/oauth/oAuthStore';
712

8-
jest.mock('@aws-amplify/core/internals/utils');
913
jest.mock('@aws-amplify/core', () => ({
1014
...jest.requireActual('@aws-amplify/core'),
1115
Hub: {
@@ -90,4 +94,20 @@ describe('tokenOrchestrator', () => {
9094
expect(newTokens?.signInDetails).toEqual(testSignInDetails);
9195
});
9296
});
97+
98+
describe('handleErrors method', () => {
99+
it('does not call clearTokens() if the error is a network error thrown from fetch handler', () => {
100+
const clearTokensSpy = jest.spyOn(tokenOrchestrator, 'clearTokens');
101+
const error = new AmplifyError({
102+
name: AmplifyErrorCode.NetworkError,
103+
message: 'Network Error',
104+
});
105+
106+
expect(() => {
107+
(tokenOrchestrator as any).handleErrors(error);
108+
}).toThrow(error);
109+
110+
expect(clearTokensSpy).not.toHaveBeenCalled();
111+
});
112+
});
93113
});

packages/auth/src/providers/cognito/tokenProvider/TokenOrchestrator.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
} from '@aws-amplify/core';
1010
import {
1111
AMPLIFY_SYMBOL,
12+
AmplifyErrorCode,
1213
assertTokenProviderConfig,
1314
isBrowser,
1415
isTokenExpired,
@@ -169,7 +170,7 @@ export class TokenOrchestrator implements AuthTokenOrchestrator {
169170

170171
private handleErrors(err: unknown) {
171172
assertServiceError(err);
172-
if (err.message !== 'Network error') {
173+
if (err.name !== AmplifyErrorCode.NetworkError) {
173174
// TODO(v6): Check errors on client
174175
this.clearTokens();
175176
}

packages/aws-amplify/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@
485485
"name": "[Storage] list (S3)",
486486
"path": "./dist/esm/storage/index.mjs",
487487
"import": "{ list }",
488-
"limit": "15.41 kB"
488+
"limit": "15.50 kB"
489489
},
490490
{
491491
"name": "[Storage] remove (S3)",
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import { HttpResponse } from '../../../../src/clients';
5+
import { getRetryDecider } from '../../../../src/clients/middleware/retry/defaultRetryDecider';
6+
import { AmplifyError } from '../../../../src/errors';
7+
import { AmplifyErrorCode } from '../../../../src/types';
8+
9+
describe('getRetryDecider', () => {
10+
const mockErrorParser = jest.fn();
11+
12+
describe('created retryDecider', () => {
13+
const mockNetworkErrorThrownFromFetch = new AmplifyError({
14+
name: AmplifyErrorCode.NetworkError,
15+
message: 'Network Error',
16+
});
17+
const mockNetworkErrorThrownFromXHRInStorage = new Error('Network Error');
18+
mockNetworkErrorThrownFromXHRInStorage.name = 'ERR_NETWORK';
19+
mockNetworkErrorThrownFromXHRInStorage.message = 'Network Error';
20+
21+
test.each([
22+
[
23+
'a network error from the fetch handler',
24+
true,
25+
mockNetworkErrorThrownFromFetch,
26+
],
27+
[
28+
'a network error from the XHR handler defined in Storage',
29+
true,
30+
mockNetworkErrorThrownFromXHRInStorage,
31+
],
32+
])('when receives %p returns %p', (_, expected, error) => {
33+
const mockResponse = {} as unknown as HttpResponse;
34+
mockErrorParser.mockReturnValueOnce(error);
35+
const retryDecider = getRetryDecider(mockErrorParser);
36+
37+
expect(retryDecider(mockResponse, error)).resolves.toBe(expected);
38+
});
39+
});
40+
});

packages/core/src/clients/middleware/retry/defaultRetryDecider.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4+
import { AmplifyErrorCode } from '../../../types';
45
import { ErrorParser, HttpResponse } from '../../types';
56

67
import { isClockSkewError } from './isClockSkewError';
@@ -55,7 +56,11 @@ const isThrottlingError = (statusCode?: number, errorCode?: string) =>
5556
(!!errorCode && THROTTLING_ERROR_CODES.includes(errorCode));
5657

5758
const isConnectionError = (error?: unknown) =>
58-
(error as Error)?.name === 'Network error';
59+
[
60+
AmplifyErrorCode.NetworkError,
61+
// TODO(vNext): unify the error code `ERR_NETWORK` used by the Storage XHR handler
62+
'ERR_NETWORK',
63+
].includes((error as Error)?.name);
5964

6065
const isServerSideError = (statusCode?: number, errorCode?: string) =>
6166
(!!statusCode && [500, 502, 503, 504].includes(statusCode)) ||

0 commit comments

Comments
 (0)