0

我目前正在使用AWS java 客户端来请求网关 API

实际代码依赖于“aws-sdk-java”,我想迁移更现代的版本“aws-sdk-java-v2”。然后,客户端将受益于非阻塞 I/O API。事实证明,从 v1 迁移到 v2 并不简单(至少对我而言)。我很乐意为此提供一些指导。

更具体地说,我需要停止com.amazonaws.AmazonWebServiceClient为更现代的课程扩展software.amazon.awssdk.services.apigateway.ApiGatewayAsyncClient课程。

我无法弄清楚代码的几个部分以正确迁移:

  • 如何提供正确的签名者software.amazon.awssdk.core.signer.Signer和/或software.amazon.awssdk.core.signer.AsyncSigner
  • 如何提供响应和错误处理程序?
  • 是以异步方式调用api的正确方法的方法吗getGatewayResponseclient

原始代码基于How to call AWS API Gateway From the Java code ?

package com.piotrfilipowicz.aws;

import com.amazonaws.AmazonServiceException;
import com.amazonaws.AmazonWebServiceClient;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.DefaultRequest;
import com.amazonaws.RequestConfig;
import com.amazonaws.auth.AWS4Signer;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.http.ExecutionContext;
import com.amazonaws.http.HttpMethodName;
import com.amazonaws.http.JsonErrorResponseHandler;
import com.amazonaws.http.JsonResponseHandler;
import com.amazonaws.internal.AmazonWebServiceRequestAdapter;
import com.amazonaws.internal.auth.DefaultSignerProvider;
import com.amazonaws.protocol.json.JsonOperationMetadata;
import com.amazonaws.protocol.json.SdkStructuredPlainJsonFactory;
import com.amazonaws.transform.JsonErrorUnmarshaller;
import com.amazonaws.transform.JsonUnmarshallerContext;
import com.amazonaws.transform.Unmarshaller;
import com.fasterxml.jackson.databind.JsonNode;

import java.io.InputStream;
import java.net.URI;
import java.util.Collections;

public class JsonApiGatewayCaller extends AmazonWebServiceClient {
    private static final String API_GATEWAY_SERVICE_NAME = "execute-api";

    private final AWSCredentialsProvider credentials;
    private final String apiKey;
    private final AWS4Signer signer;

    private final JsonResponseHandler<ApiGatewayResponse> responseHandler;
    private final JsonErrorResponseHandler errorResponseHandler;

    public JsonApiGatewayCaller(String accessKey, String secretAccessKey, String apiKey, String region, URI endpoint) {

        super(new ClientConfiguration());

        this.credentials = new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, secretAccessKey));
        this.apiKey = apiKey;
        this.endpoint = endpoint;

        this.signer = new AWS4Signer();
        this.signer.setServiceName(API_GATEWAY_SERVICE_NAME);
        this.signer.setRegionName(region);

        final JsonOperationMetadata metadata = new JsonOperationMetadata().withHasStreamingSuccessResponse(false).withPayloadJson(false);
        final Unmarshaller<ApiGatewayResponse, JsonUnmarshallerContext> responseUnmarshaller = in -> new ApiGatewayResponse(in.getHttpResponse());
        this.responseHandler = SdkStructuredPlainJsonFactory.SDK_JSON_FACTORY.createResponseHandler(metadata, responseUnmarshaller);

        JsonErrorUnmarshaller defaultErrorUnmarshaller = new JsonErrorUnmarshaller(ApiGatewayException.class, null) {
            @Override
            public AmazonServiceException unmarshall(JsonNode jsonContent) throws Exception {
                return new ApiGatewayException(jsonContent.toString());
            }
        };

        this.errorResponseHandler = SdkStructuredPlainJsonFactory.SDK_JSON_FACTORY.createErrorResponseHandler(
                Collections.singletonList(defaultErrorUnmarshaller), null);
    }

    public ApiGatewayResponse execute(HttpMethodName method, String resourcePath, InputStream content) {
        final ExecutionContext executionContext = createExecutionContext();

        DefaultRequest request = prepareRequest(method, resourcePath, content);

        RequestConfig requestConfig = new AmazonWebServiceRequestAdapter(request.getOriginalRequest());

        return this.client.execute(request, responseHandler, errorResponseHandler, executionContext, requestConfig).getAwsResponse();
    }

    private DefaultRequest prepareRequest(HttpMethodName method, String resourcePath, InputStream content) {
        DefaultRequest request = new DefaultRequest(API_GATEWAY_SERVICE_NAME);
        request.setHttpMethod(method);
        request.setContent(content);
        request.setEndpoint(this.endpoint);
        request.setResourcePath(resourcePath);
        request.setHeaders(Collections.singletonMap("Content-type", "application/json"));
        return request;
    }

    private ExecutionContext createExecutionContext() {
        final ExecutionContext executionContext = ExecutionContext.builder().withSignerProvider(
                new DefaultSignerProvider(this, signer)).build();
        executionContext.setCredentialsProvider(credentials);
        return executionContext;
    }

}

到目前为止,我的迁移代码看起来像这样


import software.amazon.awssdk.core.client.config.ClientAsyncConfiguration;
import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption;
import software.amazon.awssdk.core.client.config.SdkAdvancedAsyncClientOption;
import software.amazon.awssdk.core.signer.AsyncSigner;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.AwsCredentials;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.services.apigateway.model.GetGatewayResponseRequest;
import software.amazon.awssdk.http.async.SdkAsyncHttpClient;
import software.amazon.awssdk.http.crt.AwsCrtAsyncHttpClient;
import software.amazon.awssdk.services.apigateway.ApiGatewayAsyncClient;
import org.apache.log4j.Logger;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class AsyncGatewayClient extends ApiGatewayAsyncClient {

    public class AwsApiCredentialsProvider implements AwsCredentialsProvider {
        private final String accessKey;
        private final String secretAccessKey;

        public AwsApiCredentialsProvider(String accessKey, String secretAccessKey) {
            this.accessKey = accessKey;
            this.secretAccessKey = secretAccessKey;
        }

        @Override
        public AwsCredentials resolveCredentials() {
            return AwsBasicCredentials.create(accessKey, secretAccessKey);
        }
    }

    public final static SdkAsyncHttpClient httpClient = AwsCrtAsyncHttpClient.builder().build();

    public AsyncGatewayClient(
       String accessKey, String secretAccessKey, String endPointString, String regionUid
    ) {
        AwsCredentialsProvider credentialsProvider = new AwsApiCredentialsProvider(accessKey, secretAccessKey);
        Region region = Region.of(regionUid);

        URI endPointUri;
        try {
            endPointUri = new URI(endPointString);
        } catch (URISyntaxException e) {
            throw new ConfigException.Missing("Endpoint is not a valid URI: " + endPointString);
        }

        ClientAsyncConfiguration overrideAsyncConfig = ClientAsyncConfiguration.builder()
                .advancedOptions(new SdkAdvancedAsyncClientOption(AsyncSigner.class), )
                .build();
        ClientOverrideConfiguration overrideConfig = ClientOverrideConfiguration.builder()
                .advancedOptions(SdkAdvancedClientOption.SIGNER, )
                .build();

        ApiGatewayAsyncClient client = ApiGatewayAsyncClient.builder()
                .httpClient(httpClient)
                .endpointOverride(endpoint)
                .overrideConfiguration(overrideConfig)
                .asyncConfiguration(overrideAsyncConfig)
                .credentialsProvider(credentialsProvider)
                .region(region)
                .build();

4

0 回答 0