Search in sources :

Example 1 with ApiException

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);
        }
    }
}
Also used : OkHttpClient(okhttp3.OkHttpClient) IOException(java.io.IOException) ApiRequestDecoratorFactory(com.amplifyframework.api.aws.auth.ApiRequestDecoratorFactory) AuthRuleRequestDecorator(com.amplifyframework.api.aws.auth.AuthRuleRequestDecorator) RequestDecorator(com.amplifyframework.api.aws.auth.RequestDecorator) HashMap(java.util.HashMap) Map(java.util.Map) ApiException(com.amplifyframework.api.ApiException)

Example 2 with ApiException

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;
}
Also used : AWSRestOperation(com.amplifyframework.api.aws.operation.AWSRestOperation) RestOperationRequest(com.amplifyframework.api.rest.RestOperationRequest) ApiException(com.amplifyframework.api.ApiException)

Example 3 with ApiException

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));
    }
}
Also used : ApiAuthException(com.amplifyframework.api.ApiException.ApiAuthException) ApiException(com.amplifyframework.api.ApiException)

Example 4 with ApiException

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.");
    }
}
Also used : URISyntaxException(java.net.URISyntaxException) URI(java.net.URI) ApiException(com.amplifyframework.api.ApiException)

Example 5 with ApiException

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);
    }
}
Also used : ApiAuthException(com.amplifyframework.api.ApiException.ApiAuthException) GraphQLRequest(com.amplifyframework.api.graphql.GraphQLRequest) Request(okhttp3.Request) JSONException(org.json.JSONException) JSONObject(org.json.JSONObject) ApiException(com.amplifyframework.api.ApiException)

Aggregations

ApiException (com.amplifyframework.api.ApiException)33 Test (org.junit.Test)12 GraphQLResponse (com.amplifyframework.api.graphql.GraphQLResponse)11 GraphQLRequest (com.amplifyframework.api.graphql.GraphQLRequest)9 AmplifyException (com.amplifyframework.AmplifyException)8 PaginatedResult (com.amplifyframework.api.graphql.PaginatedResult)7 JSONObject (org.json.JSONObject)7 Consumer (com.amplifyframework.core.Consumer)6 IOException (java.io.IOException)6 Request (okhttp3.Request)6 MockResponse (okhttp3.mockwebserver.MockResponse)6 JSONException (org.json.JSONException)6 ApiAuthException (com.amplifyframework.api.ApiException.ApiAuthException)5 BlogOwner (com.amplifyframework.testmodels.commentsblog.BlogOwner)5 RecordedRequest (okhttp3.mockwebserver.RecordedRequest)5 NonNull (androidx.annotation.NonNull)4 RestOperationRequest (com.amplifyframework.api.rest.RestOperationRequest)4 RestResponse (com.amplifyframework.api.rest.RestResponse)4 Action (com.amplifyframework.core.Action)4 Cancelable (com.amplifyframework.core.async.Cancelable)4