All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alipay.api.kms.aliyun.AliyunRpcClient Maven / Gradle / Ivy

package com.alipay.api.kms.aliyun;

import com.alibaba.fastjson.JSON;
import com.alipay.api.internal.util.StringUtils;
import com.alipay.api.kms.aliyun.credentials.AccessKeyCredentials;
import com.alipay.api.kms.aliyun.credentials.BasicSessionCredentials;
import com.alipay.api.kms.aliyun.credentials.ICredentials;
import com.alipay.api.kms.aliyun.credentials.provider.*;
import com.alipay.api.kms.aliyun.exceptions.ClientException;
import com.alipay.api.kms.aliyun.exceptions.ServerException;
import com.alipay.api.kms.aliyun.http.*;
import com.alipay.api.kms.aliyun.utils.BackoffUtils;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class AliyunRpcClient {
    private static final String SIGNATURE_BEGIN = "string to sign is:";
    private final String endpoint;
    private final CompatibleUrlConnClient httpClient;
    private ICredentialsProvider credentialsProvider;
    private BackoffStrategy backoffStrategy;
    private final CredentialsProviderFactory factory;

    public AliyunRpcClient(String endpoint) {
        this.endpoint = endpoint;
        this.httpClient = new CompatibleUrlConnClient();
        this.backoffStrategy = new FullJitterBackoffStrategy();
        this.factory = new CredentialsProviderFactory();
    }

    public AliyunRpcClient(String endpoint, String accessKeyId, String accessKeySecret) {
        this(endpoint);
        this.credentialsProvider = getAccessKeyCredentialsProvider(accessKeyId, accessKeySecret);
    }

    public AliyunRpcClient(String endpoint, String accessKeyId, String accessKeySecret, String securityToken) {
        this(endpoint);
        this.credentialsProvider = getStsTokenCredentialsProvider(accessKeyId, accessKeySecret, securityToken);
    }

    public AliyunRpcClient(String endpoint, String accessKeyId, String accessKeySecret, String roleArn, String roleSessionName) {
        this(endpoint);
        this.credentialsProvider = getRamRoleArnCredentialsProvider(accessKeyId, accessKeySecret, roleArn, roleSessionName, "");
    }

    public AliyunRpcClient(String endpoint, String accessKeyId, String accessKeySecret, String roleArn, String roleSessionName,
                           String policy) {
        this(endpoint);
        this.credentialsProvider = getRamRoleArnCredentialsProvider(accessKeyId, accessKeySecret, roleArn, roleSessionName, policy);
    }

    public AliyunRpcClient(String endpoint, String roleName) {
        this(endpoint);
        this.credentialsProvider = getEcsRamRoleCredentialsProvider(roleName);
    }

    public AliyunRpcClient withBackoffStrategy(BackoffStrategy backoffStrategy) {
        this.backoffStrategy = backoffStrategy;
        return this;
    }

    private ICredentialsProvider getAccessKeyCredentialsProvider(String accessKeyId, String accessKeySecret) {
        return factory.createCredentialsProvider(new StaticCredentialsProvider(new AccessKeyCredentials(accessKeyId,
                accessKeySecret)));
    }

    private ICredentialsProvider getStsTokenCredentialsProvider(String accessKeyId, String accessKeySecret, String securityToken) {
        return factory.createCredentialsProvider(new StaticCredentialsProvider(new BasicSessionCredentials(accessKeyId,
                accessKeySecret, securityToken)));
    }

    private ICredentialsProvider getEcsRamRoleCredentialsProvider(String roleName) {
        if (StringUtils.isEmpty(roleName)) {
            throw new IllegalArgumentException("The roleName is empty");
        }
        return factory.createCredentialsProvider(new EcsRamRoleCredentialsProvider(roleName));
    }

    private ICredentialsProvider getRamRoleArnCredentialsProvider(String accessKeyId, String accessKeySecret, String roleArn,
                                                                  String roleSessionName, String policy) {
        if (StringUtils.isEmpty(accessKeyId) || StringUtils.isEmpty(accessKeySecret)) {
            throw new IllegalArgumentException("The accessKeyId or accessKeySecret is empty");
        }
        if (StringUtils.isEmpty(roleArn) || StringUtils.isEmpty(roleSessionName)) {
            throw new IllegalArgumentException("The roleArn or roleSessionName is empty");
        }
        if (StringUtils.isEmpty(policy)) {
            return factory.createCredentialsProvider(new RamRoleArnCredentialsProvider(accessKeyId, accessKeySecret, roleArn,
                    roleSessionName));
        }
        return factory.createCredentialsProvider(new RamRoleArnCredentialsProvider(accessKeyId, accessKeySecret, roleArn,
                roleSessionName, policy));
    }

    public  HttpResponse doRequest(AliyunRequest request) throws ClientException {
        int retryTimes = 0;
        Long waitTimeExponential;
        while ((waitTimeExponential = backoffStrategy.getWaitTimeExponential(retryTimes)) > 0) {
            try {
                return this.doAction(request);
            } catch (ClientException e) {
                if (!BackoffUtils.judgeNeedBackoff(e)) {
                    throw e;
                }
                sleep(waitTimeExponential);
            }
            retryTimes = retryTimes + 1;
        }
        throw new ClientException("No results were obtained from KMS, after retrying " + retryTimes + " times");
    }

    private void sleep(Long time) {
        try {
            Thread.sleep(time);
        } catch (InterruptedException ignore) {
        }
    }

    private  HttpResponse doAction(AliyunRequest request) throws ClientException {
        HttpResponse response;
        try {
            ICredentials credentials = this.credentialsProvider.getCredentials();
            HttpRequest httpRequest = request.signRequest(credentials, endpoint);
            response = this.httpClient.syncInvoke(httpRequest);
            return response;
        } catch (IOException e) {
            throw new ClientException("ServerUnreachable", "Server unreachable: connection " + request.getUrl() + " failed", e);
        } catch (NoSuchAlgorithmException e) {
            throw new ClientException("InvalidMD5Algorithm", "MD5 hash is not supported by client side.", e);
        } catch (Exception e) {
            throw new ClientException(e);
        }
    }

    public  T getAcsResponse(AliyunRequest request) throws ClientException {
        HttpResponse baseResponse = this.doRequest(request);
        return parseAcsResponse(request, baseResponse);
    }

    private  T parseAcsResponse(AliyunRequest request, HttpResponse baseResponse) throws ClientException {
        FormatType format = baseResponse.getHttpContentType();
        if (FormatType.JSON != format && FormatType.XML != format) {
            throw new ClientException(String.format("Server response has a bad format type: %s;\nThe original return is: %s;", format, baseResponse.getHttpContentString()));
        }
        if (baseResponse.isSuccess()) {
            return readResponse(request.getResponseClass(), baseResponse, format);
        } else {
            AliyunError error = readError(baseResponse, format);
            if (500 <= baseResponse.getStatus()) {
                throw new ServerException(error.getErrorCode(), error.getErrorMessage(), error.getRequestId());
            } else if (400 == baseResponse.getStatus() && ("IncompleteSignature".equals(error.getErrorCode())
                    || "SignatureDoesNotMatch".equals(error.getErrorCode()))) {
                String errorMessage = error.getErrorMessage();
                Pattern startPattern = Pattern.compile(SIGNATURE_BEGIN);
                Matcher startMatcher = startPattern.matcher(errorMessage);
                if (startMatcher.find()) {
                    int start = startMatcher.end();
                    String errorStrToSign = errorMessage.substring(start);
                    if (request.strToSign.equals(errorStrToSign)) {
                        throw new ClientException("InvalidAccessKeySecret", "Specified Access Key Secret is not valid.", error.getRequestId());
                    }
                }
            }
            throw new ClientException(error.getErrorCode(), error.getErrorMessage(), error.getRequestId(), error.getErrorDescription());
        }
    }

    protected  T readResponse(Class clasz, HttpResponse httpResponse, FormatType format) throws ClientException {
        UnmarshallerContext context = new UnmarshallerContext();
        T response;
        String stringContent = httpResponse.getHttpContentString();
        if (stringContent == null) {
            throw new ClientException("InvalidServerResponse", "Failed to parse the response. The request was succeeded, but the server returned an empty HTTP body.");
        }
        try {
            response = clasz.getConstructor().newInstance();
        } catch (Exception e) {
            throw new ClientException("InvalidResponseClass", "Unable to allocate " + clasz.getName() + " class");
        }
        context.setResponseMap(JSON.parseObject(stringContent).getInnerMap());
        context.setHttpResponse(httpResponse);
        response.getInstance(context);
        return response;

    }

    private AliyunError readError(HttpResponse httpResponse, FormatType format) throws ClientException {
        AliyunError error = new AliyunError();
        UnmarshallerContext context = new UnmarshallerContext();
        String stringContent = httpResponse.getHttpContentString();
        if (stringContent == null) {
            error.setErrorCode("(null)");
            error.setErrorMessage("(null)");
            error.setRequestId("(null)");
            error.setStatusCode(httpResponse.getStatus());
            return error;
        } else {
            context.setResponseMap(JSON.parseObject(stringContent).getInnerMap());
            return error.getInstance(context);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy