use of com.amplifyframework.api.ApiException in project amplify-android by aws-amplify.
the class AWSApiPlugin method configure.
@Override
public void configure(JSONObject pluginConfiguration, @NonNull Context context) throws ApiException {
// Null-check for configuration is done inside readFrom method
AWSApiPluginConfiguration pluginConfig = AWSApiPluginConfigurationReader.readFrom(pluginConfiguration);
for (Map.Entry<String, ApiConfiguration> entry : pluginConfig.getApis().entrySet()) {
final String apiName = entry.getKey();
final ApiConfiguration apiConfiguration = entry.getValue();
final EndpointType endpointType = apiConfiguration.getEndpointType();
final OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
okHttpClientBuilder.addNetworkInterceptor(UserAgentInterceptor.using(UserAgent::string));
okHttpClientBuilder.eventListener(new ApiConnectionEventListener());
OkHttpConfigurator configurator = apiConfigurators.get(apiName);
if (configurator != null) {
configurator.applyConfiguration(okHttpClientBuilder);
}
final ApiRequestDecoratorFactory requestDecoratorFactory = new ApiRequestDecoratorFactory(authProvider, apiConfiguration.getAuthorizationType(), apiConfiguration.getRegion(), apiConfiguration.getEndpointType(), apiConfiguration.getApiKey());
ClientDetails clientDetails = null;
if (EndpointType.REST.equals(endpointType)) {
if (apiConfiguration.getAuthorizationType() != AuthorizationType.NONE) {
AuthorizationType authorizationType = apiConfiguration.getAuthorizationType();
okHttpClientBuilder.addInterceptor(chain -> {
try {
RequestDecorator decorator = requestDecoratorFactory.forAuthType(authorizationType);
return chain.proceed(decorator.decorate(chain.request()));
} catch (ApiException.ApiAuthException apiAuthException) {
throw new IOException("Failed to decorate request for authorization.", apiAuthException);
}
});
}
clientDetails = new ClientDetails(apiConfiguration, okHttpClientBuilder.build(), null, requestDecoratorFactory);
restApis.add(apiName);
} else if (EndpointType.GRAPHQL.equals(endpointType)) {
final SubscriptionAuthorizer subscriptionAuthorizer = new SubscriptionAuthorizer(apiConfiguration, authProvider);
final SubscriptionEndpoint subscriptionEndpoint = new SubscriptionEndpoint(apiConfiguration, gqlResponseFactory, subscriptionAuthorizer);
clientDetails = new ClientDetails(apiConfiguration, okHttpClientBuilder.build(), subscriptionEndpoint, requestDecoratorFactory);
gqlApis.add(apiName);
}
if (clientDetails != null) {
apiDetails.put(apiName, clientDetails);
}
}
}
use of com.amplifyframework.api.ApiException in project amplify-android by aws-amplify.
the class AWSApiPlugin method createRestOperation.
/**
* Creates a HTTP REST operation.
* @param type Operation type
* @param options Request options
* @param onResponse Called when a response is available
* @param onFailure Called when no response is available
* @return A REST Operation
*/
private RestOperation createRestOperation(String apiName, HttpMethod type, RestOptions options, Consumer<RestResponse> onResponse, Consumer<ApiException> onFailure) throws ApiException {
final ClientDetails clientDetails = apiDetails.get(apiName);
if (clientDetails == null) {
throw new ApiException("No client information for API named " + apiName, "Check your amplify configuration to make sure there " + "is a correctly configured section for " + apiName);
}
RestOperationRequest operationRequest;
switch(type) {
// These ones are special, they don't use any data.
case HEAD:
case GET:
case DELETE:
if (options.hasData()) {
throw new ApiException("HTTP method does not support data object! " + type, "Try sending the request without any data in the options.");
}
operationRequest = new RestOperationRequest(type, options.getPath(), options.getHeaders(), options.getQueryParameters());
break;
case PUT:
case POST:
case PATCH:
operationRequest = new RestOperationRequest(type, options.getPath(), options.getData() == null ? new byte[0] : options.getData(), options.getHeaders(), options.getQueryParameters());
break;
default:
throw new ApiException("Unknown REST operation type: " + type, "Send support type for the request.");
}
AWSRestOperation operation = new AWSRestOperation(operationRequest, clientDetails.apiConfiguration.getEndpoint(), clientDetails.okHttpClient, onResponse, onFailure);
operation.start();
return operation;
}
use of com.amplifyframework.api.ApiException in project amplify-android by aws-amplify.
the class MutiAuthSubscriptionOperation method dispatchRequest.
private void dispatchRequest() {
LOG.debug("Processing subscription request: " + getRequest().getContent());
// If the auth types iterator still has items to return;
if (authTypes.hasNext()) {
// Advance the iterator, and get the next auth type to try.
AuthorizationType authorizationType = authTypes.next();
LOG.debug("Attempting to subscribe with " + authorizationType.name());
GraphQLRequest<T> request = getRequest();
// added to the request.
if (authTypes.isOwnerBasedRule()) {
try {
request = requestDecorator.decorate(request, authorizationType);
} catch (ApiAuthException apiAuthException) {
// For ApiAuthExceptions, just queue up a dispatchRequest call. If there are no
// other auth types left, it will emit the error to the client's callback
// because authTypes.hasNext() will be false.
subscriptionFuture = executorService.submit(this::dispatchRequest);
return;
} catch (ApiException apiException) {
LOG.warn("Unable to automatically add an owner to the request.", apiException);
emitErrorAndCancelSubscription(apiException);
return;
}
}
subscriptionEndpoint.requestSubscription(request, authorizationType, subscriptionId -> {
MutiAuthSubscriptionOperation.this.subscriptionId = subscriptionId;
onSubscriptionStart.accept(subscriptionId);
}, response -> {
if (response.hasErrors() && hasAuthRelatedErrors(response) && authTypes.hasNext()) {
// If there are auth-related errors, dispatch an ApiAuthException
executorService.submit(this::dispatchRequest);
} else {
// Otherwise, we just want to dispatch it as a next item and
// let callers deal with the errors.
onNextItem.accept(response);
}
}, apiException -> {
LOG.warn("A subscription error occurred.", apiException);
if (apiException instanceof ApiAuthException && authTypes.hasNext()) {
executorService.submit(this::dispatchRequest);
} else {
emitErrorAndCancelSubscription(apiException);
}
}, onSubscriptionComplete);
} else {
emitErrorAndCancelSubscription(new ApiException("Unable to establish subscription connection.", AmplifyException.TODO_RECOVERY_SUGGESTION));
}
}
use of com.amplifyframework.api.ApiException in project amplify-android by aws-amplify.
the class SubscriptionAuthorizer method getRequestEndpoint.
private URI getRequestEndpoint(boolean connectionFlag) throws ApiException {
try {
String baseUrl = configuration.getEndpoint();
String connectionUrl = connectionFlag ? baseUrl + "/connect" : baseUrl;
return new URI(connectionUrl);
} catch (URISyntaxException uriException) {
throw new ApiException("Error constructing canonical URI for IAM request signature", uriException, "Verify that the API configuration contains valid GraphQL endpoint.");
}
}
use of com.amplifyframework.api.ApiException in project amplify-android by aws-amplify.
the class SubscriptionEndpoint method requestSubscription.
synchronized <T> void requestSubscription(@NonNull GraphQLRequest<T> request, @NonNull AuthorizationType authType, @NonNull Consumer<String> onSubscriptionStarted, @NonNull Consumer<GraphQLResponse<T>> onNextItem, @NonNull Consumer<ApiException> onSubscriptionError, @NonNull Action onSubscriptionComplete) {
Objects.requireNonNull(request);
Objects.requireNonNull(onSubscriptionStarted);
Objects.requireNonNull(onNextItem);
Objects.requireNonNull(onSubscriptionError);
Objects.requireNonNull(onSubscriptionComplete);
// force a new connection to be created.
if (webSocketListener == null || webSocketListener.isDisconnectedState()) {
webSocketListener = new AmplifyWebSocketListener();
try {
webSocket = okHttpClient.newWebSocket(new Request.Builder().url(buildConnectionRequestUrl(authType)).addHeader("Sec-WebSocket-Protocol", "graphql-ws").build(), webSocketListener);
} catch (ApiException apiException) {
onSubscriptionError.accept(apiException);
return;
}
}
final String subscriptionId = UUID.randomUUID().toString();
pendingSubscriptionIds.add(subscriptionId);
// Every request waits here for the connection to be ready.
Connection connection = webSocketListener.waitForConnectionReady();
if (connection.hasFailure()) {
// If the latch didn't count all the way down
if (pendingSubscriptionIds.remove(subscriptionId)) {
// The subscription was pending, so we need to emit an error.
onSubscriptionError.accept(new ApiException(connection.getFailureReason(), AmplifyException.TODO_RECOVERY_SUGGESTION));
return;
}
}
try {
webSocket.send(new JSONObject().put("id", subscriptionId).put("type", "start").put("payload", new JSONObject().put("data", request.getContent()).put("extensions", new JSONObject().put("authorization", authorizer.createHeadersForSubscription(request, authType)))).toString());
} catch (JSONException | ApiException exception) {
// If the subscriptionId was still pending, then we can call the onSubscriptionError
if (pendingSubscriptionIds.remove(subscriptionId)) {
if (exception instanceof ApiAuthException) {
// Don't wrap it if it's an ApiAuthException.
onSubscriptionError.accept((ApiAuthException) exception);
} else {
onSubscriptionError.accept(new ApiException("Failed to construct subscription registration message.", exception, AmplifyException.TODO_RECOVERY_SUGGESTION));
}
}
return;
}
Subscription<T> subscription = new Subscription<>(onNextItem, onSubscriptionError, onSubscriptionComplete, responseFactory, request.getResponseType(), request);
subscriptions.put(subscriptionId, subscription);
if (subscription.awaitSubscriptionReady()) {
pendingSubscriptionIds.remove(subscriptionId);
onSubscriptionStarted.accept(subscriptionId);
}
}
Aggregations