Skip to content

Commit 0571504

Browse files
authored
fix(api): move error handling to multi-auth operation (#1399)
1 parent d65b5bb commit 0571504

File tree

4 files changed

+53
-47
lines changed

4 files changed

+53
-47
lines changed

aws-datastore/src/main/java/com/amplifyframework/datastore/appsync/AppSyncExtensions.java renamed to aws-api-appsync/src/main/java/com/amplifyframework/datastore/appsync/AppSyncExtensions.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,15 @@ public String toString() {
129129
'}';
130130
}
131131

132+
/**
133+
* Checks whether the current extension data indicates an authorization related error.
134+
* @return True if it is authorization related, false otherwise.
135+
*/
136+
public boolean isUnauthorizedErrorType() {
137+
return AppSyncExtensions.AppSyncErrorType.UNAUTHORIZED.equals(this.getErrorType()) ||
138+
AppSyncExtensions.AppSyncErrorType.UNAUTHORIZED_EXCEPTION.equals(this.getErrorType());
139+
}
140+
132141
/**
133142
* An enumeration of the various error types that we expect
134143
* to see in the value of {@link AppSyncExtensions#getErrorType()}.
@@ -151,6 +160,11 @@ public enum AppSyncErrorType {
151160
*/
152161
OPERATION_DISABLED("OperationDisabled"),
153162

163+
/**
164+
* An Unauthorized error will occur if the provided credentials are not authorized for the requested operation.
165+
*/
166+
UNAUTHORIZED_EXCEPTION("UnauthorizedException"),
167+
154168
/**
155169
* An Unauthorized error will occur if the provided credentials are not authorized for the requested operation.
156170
*/

aws-api/src/main/java/com/amplifyframework/api/aws/MultiAuthAppSyncGraphQLOperation.java

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@
2929
import com.amplifyframework.core.Amplify;
3030
import com.amplifyframework.core.Consumer;
3131
import com.amplifyframework.core.model.auth.AuthorizationTypeIterator;
32+
import com.amplifyframework.datastore.appsync.AppSyncExtensions;
3233
import com.amplifyframework.logging.Logger;
34+
import com.amplifyframework.util.Empty;
3335

3436
import java.io.IOException;
3537
import java.util.Objects;
@@ -116,7 +118,7 @@ private void dispatchRequest() {
116118
} catch (ApiException apiException) {
117119
LOG.warn("Failed to make a successful request with " + authType, apiException);
118120
// Only queue up a retry if it's an auth-related exception.
119-
if (apiException instanceof ApiAuthException) {
121+
if (apiException instanceof ApiAuthException && authTypes.hasNext()) {
120122
executorService.submit(this::dispatchRequest);
121123
} else {
122124
onFailure.accept(apiException);
@@ -141,6 +143,16 @@ public void cancel() {
141143
}
142144
}
143145

146+
private boolean hasAuthRelatedErrors(GraphQLResponse<R> response) {
147+
for (GraphQLResponse.Error error : response.getErrors()) {
148+
if (!Empty.check(error.getExtensions())) {
149+
AppSyncExtensions extensions = new AppSyncExtensions(error.getExtensions());
150+
return extensions.isUnauthorizedErrorType();
151+
}
152+
}
153+
return false;
154+
}
155+
144156
static <R> Builder<R> builder() {
145157
return new Builder<>();
146158
}
@@ -165,17 +177,8 @@ public void onResponse(@NonNull Call call, @NonNull Response response) {
165177

166178
try {
167179
GraphQLResponse<R> graphQLResponse = wrapResponse(jsonResponse);
168-
if (graphQLResponse.hasErrors()) {
169-
for (GraphQLResponse.Error error : graphQLResponse.getErrors()) {
170-
if (error.getExtensions() != null &&
171-
UNAUTHORIZED_EXCEPTION.equals(error.getExtensions().get("errorType"))) {
172-
executorService.submit(MultiAuthAppSyncGraphQLOperation.this::dispatchRequest);
173-
return;
174-
}
175-
}
176-
onFailure.accept(new ApiException("The server response contains errors:" +
177-
graphQLResponse.getErrors().toString(),
178-
AmplifyException.TODO_RECOVERY_SUGGESTION));
180+
if (graphQLResponse.hasErrors() && hasAuthRelatedErrors(graphQLResponse) && authTypes.hasNext()) {
181+
executorService.submit(MultiAuthAppSyncGraphQLOperation.this::dispatchRequest);
179182
} else {
180183
onResponse.accept(graphQLResponse);
181184
}

aws-api/src/main/java/com/amplifyframework/api/aws/MutiAuthSubscriptionOperation.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@
2828
import com.amplifyframework.core.Amplify;
2929
import com.amplifyframework.core.Consumer;
3030
import com.amplifyframework.core.model.auth.AuthorizationTypeIterator;
31+
import com.amplifyframework.datastore.appsync.AppSyncExtensions;
3132
import com.amplifyframework.logging.Logger;
33+
import com.amplifyframework.util.Empty;
3234

3335
import java.util.Objects;
3436
import java.util.concurrent.ExecutorService;
@@ -37,7 +39,6 @@
3739

3840
final class MutiAuthSubscriptionOperation<T> extends GraphQLOperation<T> {
3941
private static final Logger LOG = Amplify.Logging.forNamespace("amplify:aws-api");
40-
private static final String UNAUTHORIZED_EXCEPTION = "UnauthorizedException";
4142

4243
private final SubscriptionEndpoint subscriptionEndpoint;
4344
private final ExecutorService executorService;
@@ -116,10 +117,19 @@ private void dispatchRequest() {
116117
MutiAuthSubscriptionOperation.this.subscriptionId = subscriptionId;
117118
onSubscriptionStart.accept(subscriptionId);
118119
},
119-
onNextItem,
120+
response -> {
121+
if (response.hasErrors() && hasAuthRelatedErrors(response) && authTypes.hasNext()) {
122+
// If there are auth-related errors, dispatch an ApiAuthException
123+
executorService.submit(this::dispatchRequest);
124+
} else {
125+
// Otherwise, we just want to dispatch it as a next item and
126+
// let callers deal with the errors.
127+
onNextItem.accept(response);
128+
}
129+
},
120130
apiException -> {
121131
LOG.warn("A subscription error occurred.", apiException);
122-
if (apiException instanceof ApiAuthException) {
132+
if (apiException instanceof ApiAuthException && authTypes.hasNext()) {
123133
executorService.submit(this::dispatchRequest);
124134
} else {
125135
emitErrorAndCancelSubscription(apiException);
@@ -151,6 +161,16 @@ public synchronized void cancel() {
151161
}
152162
}
153163

164+
private boolean hasAuthRelatedErrors(GraphQLResponse<T> response) {
165+
for (GraphQLResponse.Error error : response.getErrors()) {
166+
if (!Empty.check(error.getExtensions())) {
167+
AppSyncExtensions extensions = new AppSyncExtensions(error.getExtensions());
168+
return extensions.isUnauthorizedErrorType();
169+
}
170+
}
171+
return false;
172+
}
173+
154174
private void emitErrorAndCancelSubscription(ApiException apiException) {
155175
cancel();
156176
onSubscriptionError.accept(apiException);

aws-api/src/main/java/com/amplifyframework/api/aws/SubscriptionEndpoint.java

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -410,32 +410,11 @@ void awaitSubscriptionCompleted() {
410410
}
411411

412412
void dispatchNextMessage(String message) {
413-
GraphQLResponse<T> response;
414413
try {
415-
response = responseFactory.buildResponse(request, message);
414+
onNextItem.accept(responseFactory.buildResponse(request, message));
416415
} catch (ApiException exception) {
417416
dispatchError(exception);
418-
return;
419-
}
420-
// If the message received has errors,
421-
if (response.hasErrors()) {
422-
// If there are auth-related errors, dispatch an ApiAuthException
423-
if (hasAuthRelatedErrors(response)) {
424-
dispatchError(new ApiAuthException(
425-
"Authorization error in subscription response: " + response.getErrors(),
426-
AmplifyException.TODO_RECOVERY_SUGGESTION)
427-
);
428-
return;
429-
}
430-
// Otherwise, just dispatch as an ApiException
431-
dispatchError(new ApiException(
432-
"Error in subscription response: " + response.getErrors(),
433-
AmplifyException.TODO_RECOVERY_SUGGESTION)
434-
);
435-
} else {
436-
onNextItem.accept(response);
437417
}
438-
439418
}
440419

441420
void dispatchError(ApiException error) {
@@ -446,16 +425,6 @@ void dispatchCompleted() {
446425
onSubscriptionComplete.call();
447426
}
448427

449-
private boolean hasAuthRelatedErrors(GraphQLResponse<T> response) {
450-
for (GraphQLResponse.Error error : response.getErrors()) {
451-
if (error.getExtensions() != null &&
452-
UNAUTHORIZED_EXCEPTION.equals(error.getExtensions().get("errorType"))) {
453-
return true;
454-
}
455-
}
456-
return false;
457-
}
458-
459428
@Override
460429
public boolean equals(Object thatObject) {
461430
if (this == thatObject) {

0 commit comments

Comments
 (0)