Skip to content

Commit 95b9ae0

Browse files
fix: account for EVENT_SUBSCRIBE_ERROR in AppSync (#14491)
* fix: account for EVENT_SUBSCRIBE_ERROR in AppSync
1 parent 6f44adf commit 95b9ae0

File tree

3 files changed

+60
-5
lines changed

3 files changed

+60
-5
lines changed

packages/api-graphql/__tests__/AWSAppSyncEventProvider.test.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,45 @@ describe('AppSyncEventProvider', () => {
227227
expect(socketCloseSpy).toHaveBeenCalledWith(3001);
228228
});
229229

230+
test('subscription observer error is triggered when a subscribe_error message is received', async () => {
231+
expect.assertions(2);
232+
233+
const observer = provider.subscribe({
234+
appSyncGraphqlEndpoint: 'ws://localhost:8080',
235+
});
236+
237+
observer.subscribe({
238+
error: e => {
239+
expect(e.errors[0].message).toEqual(
240+
'Connection failed: AuthorizationError: Not authorized to access channel',
241+
);
242+
},
243+
});
244+
245+
await fakeWebSocketInterface?.standardConnectionHandshake();
246+
await fakeWebSocketInterface?.startAckMessage({
247+
connectionTimeoutMs: 100,
248+
});
249+
250+
// Send a subscribe_error message
251+
await fakeWebSocketInterface?.sendDataMessage({
252+
id: fakeWebSocketInterface?.webSocket.subscriptionId,
253+
type: MESSAGE_TYPES.EVENT_SUBSCRIBE_ERROR,
254+
errors: [
255+
{
256+
errorType: 'AuthorizationError',
257+
message: 'Not authorized to access channel',
258+
},
259+
],
260+
});
261+
262+
// Verify error was logged
263+
expect(loggerSpy).toHaveBeenCalledWith(
264+
'DEBUG',
265+
expect.stringContaining('Connection failed:'),
266+
);
267+
});
268+
230269
test('subscription observer error is not triggered when a connection is formed and a retriable connection_error data message is received', async () => {
231270
expect.assertions(2);
232271

packages/api-graphql/src/Providers/AWSWebSocketProvider/index.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,10 @@ export abstract class AWSWebSocketProvider {
684684
return;
685685
}
686686

687-
if (type === MESSAGE_TYPES.GQL_ERROR) {
687+
if (
688+
type === MESSAGE_TYPES.GQL_ERROR ||
689+
type === MESSAGE_TYPES.EVENT_SUBSCRIBE_ERROR
690+
) {
688691
const subscriptionState = SUBSCRIPTION_STATUS.FAILED;
689692
if (observer) {
690693
this.subscriptionObserverMap.set(id, {
@@ -697,15 +700,23 @@ export abstract class AWSWebSocketProvider {
697700
subscriptionState,
698701
});
699702

700-
this.logger.debug(
701-
`${CONTROL_MSG.CONNECTION_FAILED}: ${JSON.stringify(payload ?? data)}`,
702-
);
703+
let errorMessage = JSON.stringify(payload ?? data);
704+
705+
if (type === MESSAGE_TYPES.EVENT_SUBSCRIBE_ERROR) {
706+
const { errors } = JSON.parse(String(message.data));
707+
if (Array.isArray(errors) && errors.length > 0) {
708+
const error = errors[0];
709+
errorMessage = `${error.errorType}: ${error.message}`;
710+
}
711+
}
712+
713+
this.logger.debug(`${CONTROL_MSG.CONNECTION_FAILED}: ${errorMessage}`);
703714

704715
observer.error({
705716
errors: [
706717
{
707718
...new GraphQLError(
708-
`${CONTROL_MSG.CONNECTION_FAILED}: ${JSON.stringify(payload ?? data)}`,
719+
`${CONTROL_MSG.CONNECTION_FAILED}: ${errorMessage}`,
709720
),
710721
},
711722
],

packages/api-graphql/src/Providers/constants.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ export enum MESSAGE_TYPES {
9393
* This is the ack response from AWS AppSync Events to EVENT_STOP message
9494
*/
9595
EVENT_COMPLETE = 'unsubscribe_success',
96+
/**
97+
* Server -> Client message.
98+
* This message type is for sending error messages from AWS AppSync Events to the client
99+
*/
100+
EVENT_SUBSCRIBE_ERROR = 'subscribe_error',
96101
}
97102

98103
export enum SUBSCRIPTION_STATUS {

0 commit comments

Comments
 (0)