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

com.volcengine.ApiClient Maven / Gradle / Ivy

There is a newer version: 1.0.75
Show newest version
/*
 * VPC OpenAPI
 * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
 *
 * OpenAPI spec version: v3.7.0
 *
 *
 * NOTE: This class is auto generated by the swagger code generator program.
 * https://github.com/swagger-api/swagger-codegen.git
 * Do not edit the class manually.
 */

package com.volcengine;

import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
import com.squareup.okhttp.*;
import com.squareup.okhttp.internal.http.HttpMethod;
import com.squareup.okhttp.logging.HttpLoggingInterceptor;
import com.squareup.okhttp.logging.HttpLoggingInterceptor.Level;
import com.volcengine.auth.Authentication;
import com.volcengine.model.AbstractResponse;
import com.volcengine.model.ResponseMetadata;
import com.volcengine.sign.Credentials;
import com.volcengine.sign.ServiceInfo;
import com.volcengine.sign.VolcstackSign;
import com.volcengine.version.Version;
import okio.Buffer;
import okio.BufferedSink;
import okio.Okio;
import org.apache.commons.lang.StringUtils;
import org.threeten.bp.LocalDate;
import org.threeten.bp.OffsetDateTime;
import org.threeten.bp.format.DateTimeFormatter;

import javax.net.ssl.*;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ApiClient {
    private final static String DefaultAuthentication = "volcengineSign";

    private boolean debugging = false;
    private Map defaultHeaderMap = new HashMap();
    private String tempFolderPath = null;

    private Map authentications;

    private DateFormat dateFormat;
    private DateFormat datetimeFormat;
    private boolean lenientDatetimeFormat;
    private int dateLength;

    private InputStream sslCaCert;
    private boolean verifyingSsl;
    private KeyManager[] keyManagers;

    private OkHttpClient httpClient;
    private JSON json;

    private HttpLoggingInterceptor loggingInterceptor;

    private Credentials credentials;
    private String region;
    private String endpoint = "open.volcengineapi.com";
    private boolean disableSSL = false;

    /*
     * Constructor for ApiClient
     */
    public ApiClient() {
        httpClient = new OkHttpClient();


        verifyingSsl = true;

        json = new JSON();

        // Set default User-Agent.
        setUserAgent(getUserAgent());

        // Setup authentications (key: authentication name, value: authentication).
        authentications = new HashMap();
        authentications.put(DefaultAuthentication, new VolcstackSign());
        // Prevent the authentications from being modified.
        authentications = Collections.unmodifiableMap(authentications);
    }

    /**
     * Get UserAgent for Header
     *
     * @return userAgent
     */
    private static String getUserAgent() {
        String format = "%s/%s/(%s;%s;%s)";

        String osInfo = System.getProperty("os.name") + "-" + System.getProperty("os.version");
        String jdkInfo = "java-" + System.getProperty("java.version");
        String arch = System.getProperty("os.arch");

        return String.format(format, Version.SDK_NAME, Version.SDK_VERSION, jdkInfo, osInfo, arch);
    }

    /**
     * Get base path
     *
     * @return Baes path
     */
    public String getEndpoint() {
        return endpoint;
    }

    /**
     * Set base path
     *
     * @param endpoint endpoint of the URL
     * @return An instance of OkHttpClient
     */
    public ApiClient setEndpoint(String endpoint) {
        this.endpoint = endpoint;
        return this;
    }

    /**
     * Get disableSSL
     *
     * @return Baes path
     */
    public boolean getDisableSSL() {
        return disableSSL;
    }

    /**
     * Set disableSSL
     *
     * @param disableSSL
     * @return An instance of OkHttpClient
     */
    public ApiClient setDisableSSL(boolean disableSSL) {
        this.disableSSL = disableSSL;
        return this;
    }

    /**
     * Get region
     *
     * @return Baes path
     */
    public String getRegion() {
        return region;
    }

    /**
     * Set region
     *
     * @param region
     * @return An instance of OkHttpClient
     */
    public ApiClient setRegion(String region) {
        this.region = region;
        Authentication authentication = getAuthentication(DefaultAuthentication);
        if (authentication instanceof VolcstackSign) {
            VolcstackSign volcengineSign = (VolcstackSign) authentication;
            volcengineSign.setRegion(region);
        }
        return this;
    }

    /**
     * Get credentials
     *
     * @return Baes path
     */
    public Credentials getCredentials() {
        return credentials;
    }

    /**
     * Set credentials
     *
     * @param credentials
     * @return An instance of OkHttpClient
     */
    public ApiClient setCredentials(Credentials credentials) {
        this.credentials = credentials;
        Authentication authentication = getAuthentication(DefaultAuthentication);
        if (authentication instanceof VolcstackSign) {
            VolcstackSign volcengineSign = (VolcstackSign) authentication;
            volcengineSign.setCredentials(credentials);
        }
        return this;
    }


    /**
     * Get HTTP client
     *
     * @return An instance of OkHttpClient
     */
    public OkHttpClient getHttpClient() {
        return httpClient;
    }

    /**
     * Set HTTP client
     *
     * @param httpClient An instance of OkHttpClient
     * @return Api Client
     */
    public ApiClient setHttpClient(OkHttpClient httpClient) {
        this.httpClient = httpClient;
        return this;
    }

    /**
     * Get JSON
     *
     * @return JSON object
     */
    public JSON getJSON() {
        return json;
    }

    /**
     * Set JSON
     *
     * @param json JSON object
     * @return Api client
     */
    public ApiClient setJSON(JSON json) {
        this.json = json;
        return this;
    }

    /**
     * True if isVerifyingSsl flag is on
     *
     * @return True if isVerifySsl flag is on
     */
    public boolean isVerifyingSsl() {
        return verifyingSsl;
    }

    /**
     * Configure whether to verify certificate and hostname when making https requests.
     * Default to true.
     * NOTE: Do NOT set to false in production code, otherwise you would face multiple types of cryptographic attacks.
     *
     * @param verifyingSsl True to verify TLS/SSL connection
     * @return ApiClient
     */
    public ApiClient setVerifyingSsl(boolean verifyingSsl) {
        this.verifyingSsl = verifyingSsl;
        applySslSettings();
        return this;
    }

    /**
     * Get SSL CA cert.
     *
     * @return Input stream to the SSL CA cert
     */
    public InputStream getSslCaCert() {
        return sslCaCert;
    }

    /**
     * Configure the CA certificate to be trusted when making https requests.
     * Use null to reset to default.
     *
     * @param sslCaCert input stream for SSL CA cert
     * @return ApiClient
     */
    public ApiClient setSslCaCert(InputStream sslCaCert) {
        this.sslCaCert = sslCaCert;
        applySslSettings();
        return this;
    }

    public KeyManager[] getKeyManagers() {
        return keyManagers;
    }

    /**
     * Configure client keys to use for authorization in an SSL session.
     * Use null to reset to default.
     *
     * @param managers The KeyManagers to use
     * @return ApiClient
     */
    public ApiClient setKeyManagers(KeyManager[] managers) {
        this.keyManagers = managers;
        applySslSettings();
        return this;
    }

    public DateFormat getDateFormat() {
        return dateFormat;
    }

    public ApiClient setDateFormat(DateFormat dateFormat) {
        this.json.setDateFormat(dateFormat);
        return this;
    }

    public ApiClient setSqlDateFormat(DateFormat dateFormat) {
        this.json.setSqlDateFormat(dateFormat);
        return this;
    }

    public ApiClient setOffsetDateTimeFormat(DateTimeFormatter dateFormat) {
        this.json.setOffsetDateTimeFormat(dateFormat);
        return this;
    }

    public ApiClient setLocalDateFormat(DateTimeFormatter dateFormat) {
        this.json.setLocalDateFormat(dateFormat);
        return this;
    }

    public ApiClient setLenientOnJson(boolean lenientOnJson) {
        this.json.setLenientOnJson(lenientOnJson);
        return this;
    }

    /**
     * Get authentications (key: authentication name, value: authentication).
     *
     * @return Map of authentication objects
     */
    public Map getAuthentications() {
        return authentications;
    }

    /**
     * Get authentication for the given name.
     *
     * @param authName The authentication name
     * @return The authentication, null if not found
     */
    public Authentication getAuthentication(String authName) {
        return authentications.get(authName);
    }


    /**
     * Set the User-Agent header's value (by adding to the default header map).
     *
     * @param userAgent HTTP request's user agent
     * @return ApiClient
     */
    public ApiClient setUserAgent(String userAgent) {
        addDefaultHeader("User-Agent", userAgent);
        return this;
    }

    /**
     * Add a default header.
     *
     * @param key   The header's key
     * @param value The header's value
     * @return ApiClient
     */
    public ApiClient addDefaultHeader(String key, String value) {
        defaultHeaderMap.put(key, value);
        return this;
    }

    /**
     * Check that whether debugging is enabled for this API client.
     *
     * @return True if debugging is enabled, false otherwise.
     */
    public boolean isDebugging() {
        return debugging;
    }

    /**
     * Enable/disable debugging for this API client.
     *
     * @param debugging To enable (true) or disable (false) debugging
     * @return ApiClient
     */
    public ApiClient setDebugging(boolean debugging) {
        if (debugging != this.debugging) {
            if (debugging) {
                loggingInterceptor = new HttpLoggingInterceptor();
                loggingInterceptor.setLevel(Level.BODY);
                httpClient.interceptors().add(loggingInterceptor);
            } else {
                httpClient.interceptors().remove(loggingInterceptor);
                loggingInterceptor = null;
            }
        }
        this.debugging = debugging;
        return this;
    }

    /**
     * The path of temporary folder used to store downloaded files from endpoints
     * with file response. The default value is null, i.e. using
     * the system's default tempopary folder.
     *
     * @return Temporary folder path
     * @see createTempFile
     */
    public String getTempFolderPath() {
        return tempFolderPath;
    }

    /**
     * Set the temporary folder path (for downloading files)
     *
     * @param tempFolderPath Temporary folder path
     * @return ApiClient
     */
    public ApiClient setTempFolderPath(String tempFolderPath) {
        this.tempFolderPath = tempFolderPath;
        return this;
    }

    /**
     * Get connection timeout (in milliseconds).
     *
     * @return Timeout in milliseconds
     */
    public int getConnectTimeout() {
        return httpClient.getConnectTimeout();
    }

    /**
     * Sets the connect timeout (in milliseconds).
     * A value of 0 means no timeout, otherwise values must be between 1 and
     *
     * @param connectionTimeout connection timeout in milliseconds
     * @return Api client
     */
    public ApiClient setConnectTimeout(int connectionTimeout) {
        httpClient.setConnectTimeout(connectionTimeout, TimeUnit.MILLISECONDS);
        return this;
    }

    /**
     * Get read timeout (in milliseconds).
     *
     * @return Timeout in milliseconds
     */
    public int getReadTimeout() {
        return httpClient.getReadTimeout();
    }

    /**
     * Sets the read timeout (in milliseconds).
     * A value of 0 means no timeout, otherwise values must be between 1 and
     * {@link Integer#MAX_VALUE}.
     *
     * @param readTimeout read timeout in milliseconds
     * @return Api client
     */
    public ApiClient setReadTimeout(int readTimeout) {
        httpClient.setReadTimeout(readTimeout, TimeUnit.MILLISECONDS);
        return this;
    }

    /**
     * Get write timeout (in milliseconds).
     *
     * @return Timeout in milliseconds
     */
    public int getWriteTimeout() {
        return httpClient.getWriteTimeout();
    }

    /**
     * Sets the write timeout (in milliseconds).
     * A value of 0 means no timeout, otherwise values must be between 1 and
     * {@link Integer#MAX_VALUE}.
     *
     * @param writeTimeout connection timeout in milliseconds
     * @return Api client
     */
    public ApiClient setWriteTimeout(int writeTimeout) {
        httpClient.setWriteTimeout(writeTimeout, TimeUnit.MILLISECONDS);
        return this;
    }

    /**
     * Format the given parameter object into string.
     *
     * @param param Parameter
     * @return String representation of the parameter
     */
    public String parameterToString(Object param) {
        if (param == null) {
            return "";
        } else if (param instanceof Date || param instanceof OffsetDateTime || param instanceof LocalDate) {
            //Serialize to json string and remove the " enclosing characters
            String jsonStr = json.serialize(param);
            return jsonStr.substring(1, jsonStr.length() - 1);
        } else if (param instanceof Collection) {
            StringBuilder b = new StringBuilder();
            for (Object o : (Collection) param) {
                if (b.length() > 0) {
                    b.append(",");
                }
                b.append(String.valueOf(o));
            }
            return b.toString();
        } else {
            return String.valueOf(param);
        }
    }

    /**
     * Formats the specified query parameter to a list containing a single {@code Pair} object.
     * 

* Note that {@code value} must not be a collection. * * @param name The name of the parameter. * @param value The value of the parameter. * @return A list containing a single {@code Pair} object. */ public List parameterToPair(String name, Object value) { List params = new ArrayList(); // preconditions if (name == null || name.isEmpty() || value == null || value instanceof Collection) return params; params.add(new Pair(name, parameterToString(value))); return params; } /** * Formats the specified collection query parameters to a list of {@code Pair} objects. *

* Note that the values of each of the returned Pair objects are percent-encoded. * * @param collectionFormat The collection format of the parameter. * @param name The name of the parameter. * @param value The value of the parameter. * @return A list of {@code Pair} objects. */ public List parameterToPairs(String collectionFormat, String name, Collection value) { List params = new ArrayList(); // preconditions if (name == null || name.isEmpty() || value == null || value.isEmpty()) { return params; } // create the params based on the collection format if ("multi".equals(collectionFormat)) { for (Object item : value) { params.add(new Pair(name, escapeString(parameterToString(item)))); } return params; } // collectionFormat is assumed to be "csv" by default String delimiter = ","; // escape all delimiters except commas, which are URI reserved // characters if ("ssv".equals(collectionFormat)) { delimiter = escapeString(" "); } else if ("tsv".equals(collectionFormat)) { delimiter = escapeString("\t"); } else if ("pipes".equals(collectionFormat)) { delimiter = escapeString("|"); } StringBuilder sb = new StringBuilder(); for (Object item : value) { sb.append(delimiter); sb.append(escapeString(parameterToString(item))); } params.add(new Pair(name, sb.substring(delimiter.length()))); return params; } /** * Sanitize filename by removing path. * e.g. ../../sun.gif becomes sun.gif * * @param filename The filename to be sanitized * @return The sanitized filename */ public String sanitizeFilename(String filename) { return filename.replaceAll(".*[/\\\\]", ""); } /** * Check if the given MIME is a JSON MIME. * JSON MIME examples: * application/json * application/json; charset=UTF8 * APPLICATION/JSON * application/vnd.company+json * "* / *" is also default to JSON * * @param mime MIME (Multipurpose Internet Mail Extensions) * @return True if the given MIME is JSON, false otherwise. */ public boolean isJsonMime(String mime) { String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$"; return mime != null && (mime.matches(jsonMime) || mime.equals("*/*")); } /** * Select the Accept header's value from the given accepts array: * if JSON exists in the given array, use it; * otherwise use all of them (joining into a string) * * @param accepts The accepts array to select from * @return The Accept header to use. If the given array is empty, * null will be returned (not to set the Accept header explicitly). */ public String selectHeaderAccept(String[] accepts) { if (accepts.length == 0) { return null; } for (String accept : accepts) { if (isJsonMime(accept)) { return accept; } } return StringUtil.join(accepts, ","); } /** * Select the Content-Type header's value from the given array: * if JSON exists in the given array, use it; * otherwise use the first one of the array. * * @param contentTypes The Content-Type array to select from * @return The Content-Type header to use. If the given array is empty, * or matches "any", JSON will be used. */ public String selectHeaderContentType(String[] contentTypes) { if (contentTypes.length == 0 || contentTypes[0].equals("*/*")) { return "application/json"; } for (String contentType : contentTypes) { if (isJsonMime(contentType)) { return contentType; } } return contentTypes[0]; } /** * Escape the given string to be used as URL query value. * * @param str String to be escaped * @return Escaped string */ public String escapeString(String str) { try { return URLEncoder.encode(str, "utf8").replaceAll("\\+", "%20"); } catch (UnsupportedEncodingException e) { return str; } } /** * Deserialize response body to Java object, according to the return type and * the Content-Type response header. * * @param Type * @param response HTTP response * @param returnType The type of the Java object * @param isCommon The flag for Universal * @return The deserialized Java object * @throws ApiException If fail to deserialize response body, i.e. cannot read response body * or the Content-Type of the response is not supported. */ @SuppressWarnings("unchecked") public T deserialize(Response response, Type returnType, boolean... isCommon) throws ApiException { if (response == null || returnType == null) { return null; } if ("byte[]".equals(returnType.toString())) { // Handle binary response (byte array). try { return (T) response.body().bytes(); } catch (IOException e) { throw new ApiException(e); } } else if (returnType.equals(File.class)) { // Handle file downloading. return (T) downloadFileFromResponse(response); } String respBody; try { if (response.body() != null) respBody = response.body().string(); else respBody = null; } catch (IOException e) { throw new ApiException(e); } if (respBody == null || "".equals(respBody)) { return null; } StringBuilder builder = new StringBuilder(); Map meta = new HashMap<>(); if (isCommon.length == 0 || !isCommon[0]) { if (!convertResponseBody(respBody, builder, meta)) { throw new ApiException( response.code(), response.headers().toMultimap(), respBody, meta.get("ResponseMetadata")); } else { respBody = builder.toString(); } } String contentType = response.headers().get("Content-Type"); if (contentType == null) { // ensuring a default content type contentType = "application/json"; } if (isJsonMime(contentType)) { T t = json.deserialize(respBody, returnType); if (t instanceof AbstractResponse) { try { Method m = t.getClass().getMethod("setResponseMetadata", ResponseMetadata.class); m.invoke(t, meta.get("ResponseMetadata")); } catch (Exception e) { throw new ApiException( e.getMessage(), response.code(), response.headers().toMultimap(), respBody, meta.get("ResponseMetadata")); } } return t; } else if (returnType.equals(String.class)) { // Expecting string, return the raw response body. return (T) respBody; } else { throw new ApiException( "Content type \"" + contentType + "\" is not supported for type: " + returnType, response.code(), response.headers().toMultimap(), respBody, meta.get("ResponseMetadata")); } } /** * Serialize the given Java object into request body according to the object's * class and the request Content-Type. * * @param obj The Java object * @param contentType The request Content-Type * @return The serialized request body * @throws ApiException If fail to serialize the given object */ public RequestBody serialize(Object obj, String contentType) throws ApiException { if (obj instanceof byte[]) { // Binary (byte array) body parameter support. return RequestBody.create(MediaType.parse(contentType), (byte[]) obj); } else if (obj instanceof File) { // File body parameter support. return RequestBody.create(MediaType.parse(contentType), (File) obj); } else if (isJsonMime(contentType)) { String content; if (obj != null) { content = json.serialize(obj); } else { content = null; } return RequestBody.create(MediaType.parse(contentType), content); } else { throw new ApiException("Content type \"" + contentType + "\" is not supported"); } } /** * Download file from the given response. * * @param response An instance of the Response object * @return Downloaded file * @throws ApiException If fail to read file content from response and write to disk */ public File downloadFileFromResponse(Response response) throws ApiException { try { File file = prepareDownloadFile(response); BufferedSink sink = Okio.buffer(Okio.sink(file)); sink.writeAll(response.body().source()); sink.close(); return file; } catch (IOException e) { throw new ApiException(e); } } /** * Prepare file for download * * @param response An instance of the Response object * @return Prepared file for the download * @throws IOException If fail to prepare file for download */ public File prepareDownloadFile(Response response) throws IOException { String filename = null; String contentDisposition = response.header("Content-Disposition"); if (contentDisposition != null && !"".equals(contentDisposition)) { // Get filename from the Content-Disposition header. Pattern pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?"); Matcher matcher = pattern.matcher(contentDisposition); if (matcher.find()) { filename = sanitizeFilename(matcher.group(1)); } } String prefix = null; String suffix = null; if (filename == null) { prefix = "download-"; suffix = ""; } else { int pos = filename.lastIndexOf("."); if (pos == -1) { prefix = filename + "-"; } else { prefix = filename.substring(0, pos) + "-"; suffix = filename.substring(pos); } // File.createTempFile requires the prefix to be at least three characters long if (prefix.length() < 3) prefix = "download-"; } if (tempFolderPath == null) return Files.createTempFile(prefix, suffix).toFile(); else return Files.createTempFile(Paths.get(tempFolderPath), prefix, suffix).toFile(); } /** * {@link #execute(Call, Type, boolean...)} * * @param Type * @param call An instance of the Call object * @return ApiResponse<T> * @throws ApiException If fail to execute the call */ public ApiResponse execute(Call call) throws ApiException { return execute(call, null); } /** * Execute HTTP call and deserialize the HTTP response body into the given return type. * * @param returnType The return type used to deserialize HTTP response body * @param The return type corresponding to (same with) returnType * @param call Call * @param isCommon The flag for Universal * @return ApiResponse object containing response status, headers and * data, which is a Java object deserialized from response body and would be null * when returnType is null. * @throws ApiException If fail to execute the call */ public ApiResponse execute(Call call, final Type returnType, boolean... isCommon) throws ApiException { try { Response response = call.execute(); T data = handleResponse(response, returnType, isCommon); return new ApiResponse(response.code(), response.headers().toMultimap(), data); } catch (IOException e) { throw new ApiException(e); } } /** * {@link #executeAsync(Call, Type, ApiCallback)} * * @param Type * @param call An instance of the Call object * @param callback ApiCallback<T> */ public void executeAsync(Call call, ApiCallback callback) { executeAsync(call, null, callback); } /** * Execute HTTP call asynchronously. * * @param Type * @param call The callback to be executed when the API call finishes * @param returnType Return type * @param callback ApiCallback * @see #execute(Call, Type, boolean...) */ @SuppressWarnings("unchecked") public void executeAsync(Call call, final Type returnType, final ApiCallback callback) { call.enqueue(new Callback() { @Override public void onFailure(Request request, IOException e) { callback.onFailure(new ApiException(e), 0, null); } @Override public void onResponse(Response response) throws IOException { T result; try { result = (T) handleResponse(response, returnType); } catch (ApiException e) { callback.onFailure(e, response.code(), response.headers().toMultimap()); return; } callback.onSuccess(result, response.code(), response.headers().toMultimap()); } }); } /** * Handle the given response, return the deserialized object when the response is successful. * * @param Type * @param response Response * @param returnType Return type * @param isCommon The flag for Universal * @return Type * @throws ApiException If the response has a unsuccessful status code or * fail to deserialize the response body */ public T handleResponse(Response response, Type returnType, boolean... isCommon) throws ApiException { if (response.isSuccessful()) { if (returnType == null || response.code() == 204) { // returning null if the returnType is not defined, // or the status code is 204 (No Content) if (response.body() != null) { try { response.body().close(); } catch (IOException e) { throw new ApiException(response.message(), e, response.code(), response.headers().toMultimap()); } } return null; } else { return deserialize(response, returnType, isCommon); } } else { String respBody = null; if (response.body() != null) { try { respBody = response.body().string(); } catch (IOException e) { throw new ApiException(response.message(), e, response.code(), response.headers().toMultimap()); } } throw new ApiException(response.message(), response.code(), response.headers().toMultimap(), respBody); } } /** * Build HTTP call with the given options. * * @param path The sub-path of the HTTP URL * @param method The request method, one of "GET", "HEAD", "OPTIONS", "POST", "PUT", "PATCH" and "DELETE" * @param queryParams The query parameters * @param collectionQueryParams The collection query parameters * @param body The request body object * @param headerParams The header parameters * @param formParams The form parameters * @param authNames The authentications to apply * @param progressRequestListener Progress request listener * @param isCommon The flag for Universal * @return The HTTP call * @throws ApiException If fail to serialize the request body object */ public Call buildCall(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map formParams, String[] authNames, ProgressRequestBody.ProgressRequestListener progressRequestListener, boolean... isCommon) throws ApiException { Request request = buildRequest(path, method, queryParams, collectionQueryParams, body, headerParams, formParams, authNames, progressRequestListener, isCommon); return httpClient.newCall(request); } private void getDefaultContentType(Map headerParams) { String contentType = headerParams.get("Content-Type"); if (contentType == null) { headerParams.put("Content-Type", "text/plain"); } } private boolean isApplicationJsonBody(Map headerParams) { String contentType = headerParams.get("Content-Type"); if (contentType == null) { return false; } if (contentType.equals("application/json")) { return true; } return false; } private boolean isPostBody(Map headerParams) { String contentType = headerParams.get("Content-Type"); if (contentType == null) { return false; } if (contentType.equals("application/x-www-form-urlencoded")) { return true; } return false; } private void updateQueryParams(List queryParams, String[] param) { queryParams.add(new Pair("Action", param[1])); queryParams.add(new Pair("Version", param[2])); } private ServiceInfo addPairAndGetServiceInfo(String path, List queryParams, Map headerParams) { String[] param = path.split("/"); if (param.length >= 6) { headerParams.put("Content-Type", param[5].replaceAll("_", "/")); } if (!isApplicationJsonBody(headerParams) && !isPostBody(headerParams)) { updateQueryParams(queryParams, param); } return new ServiceInfo(param[3], param[4]); } private String getTruePath(String path, Map headerParams) { if (isApplicationJsonBody(headerParams) || isPostBody(headerParams)) { String[] param = path.split("/"); return "/?Action=" + param[1] + "&Version=" + param[2]; } else { return "/"; } } @SuppressWarnings("all") private boolean convertResponseBody(String source, StringBuilder stringBuilder, Map m) { Type t = new TypeToken>() { }.getType(); Map temp = json.deserialize(source, t); if (temp.containsKey("ResponseMetadata")) { ResponseMetadata meta = json.deserialize(json.serialize(temp.get("ResponseMetadata")), new TypeToken() { }.getType()); m.put("ResponseMetadata", meta); if (meta.getError() != null) { return false; } if (temp.containsKey("Result")) { stringBuilder.append(json.serialize(temp.get("Result"))); } else { stringBuilder.append(json.serialize(new HashMap())); } return true; } return false; } private void buildSimpleRequest(Object body, List queryParams, Map headerParams, StringBuilder builder, FormEncodingBuilder formBuilder, String chain, boolean... isCommon) throws Exception { if (body == null) { return; } if (isApplicationJsonBody(headerParams)) { builder.append(json.serialize(body)); return; } Class clazz = body.getClass(); if (isCommon.length > 0 && isCommon[0]) { try { @SuppressWarnings("unchecked") Map map = (Map) body; if (isPostBody(headerParams)) { for (Entry entry : map.entrySet()) { formBuilder.add(entry.getKey(), entry.getValue().toString()); } } else { for (Entry entry : map.entrySet()) { Pair pair = new Pair(entry.getKey(), entry.getValue().toString()); queryParams.add(pair); } } } catch (Exception e) { throw new ApiException(e); } } if (!clazz.getName().startsWith("com.volcengine")) { if (isPostBody(headerParams)) { formBuilder.add(chain, body.toString()); } else { Pair pair = new Pair(chain, body.toString()); queryParams.add(pair); } return; } if (!chain.equals("")) { chain = chain + "."; } for (Field field : clazz.getDeclaredFields()) { if (field.getAnnotation(SerializedName.class) != null) { field.setAccessible(true); Object value = field.get(body); if (value == null) { continue; } if (value instanceof List) { int count = 0; for (Object o : (List) value) { String key = chain + getMethodName(field.getName()) + "." + (++count); buildSimpleRequest(o, queryParams, headerParams, builder, formBuilder, key); } } else { if (!field.getType().getName().startsWith("com.volcengine")) { buildBodyOrParameter(field, value, queryParams, headerParams, builder, formBuilder, chain); } else if (field.getType().isEnum()) { try { Method method = field.getType().getDeclaredMethod("getValue"); Object v = method.invoke(value); if (v != null) { buildBodyOrParameter(field, v, queryParams, headerParams, builder, formBuilder, chain); } } catch (NoSuchMethodException e) { throw new ApiException("sdk internal error,please contract us in github,ErrorCode is EnumNotGetValueMethod"); } } else { String key = chain + getMethodName(field.getName()); buildSimpleRequest(value, queryParams, headerParams, builder, formBuilder, key); } } } } } private void buildBodyOrParameter(Field field, Object v, List queryParams, Map headerParams, StringBuilder builder, FormEncodingBuilder formBuilder, String chain) throws Exception { String name; String defaultName = getMethodName(field.getName()); if (field.getAnnotation(SerializedName.class) != null) { SerializedName s = field.getAnnotation(SerializedName.class); if (!s.value().equals(defaultName)) { name = s.value(); } else { name = defaultName; } } else { name = defaultName; } if (isPostBody(headerParams)) { formBuilder.add(chain + name, v.toString()); } else { Pair pair = new Pair(chain + name, v.toString()); queryParams.add(pair); } } private String getMethodName(String fieldName) throws Exception { char[] chars = fieldName.toCharArray(); chars[0] = toUpperCase(chars[0]); return String.valueOf(chars); } private char toUpperCase(char c) { if (97 <= c && c <= 122) { c ^= 32; } return c; } /** * Build an HTTP request with the given options. * * @param path The sub-path of the HTTP URL * @param method The request method, one of "GET", "HEAD", "OPTIONS", "POST", "PUT", "PATCH" and "DELETE" * @param queryParams The query parameters * @param collectionQueryParams The collection query parameters * @param body The request body object * @param headerParams The header parameters * @param formParams The form parameters * @param authNames The authentications to apply * @param progressRequestListener Progress request listener * @param isCommon The flag for Universal * @return The HTTP request * @throws ApiException If fail to serialize the request body object */ public Request buildRequest(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map formParams, String[] authNames, ProgressRequestBody.ProgressRequestListener progressRequestListener, boolean... isCommon) throws ApiException { getDefaultContentType(headerParams); ServiceInfo serviceInfo = addPairAndGetServiceInfo(path, queryParams, headerParams); //rebuild method method = serviceInfo.getMethod().toUpperCase(); String truePath = getTruePath(path, headerParams); String contentType = headerParams.get("Content-Type"); StringBuilder bodyBuilder = new StringBuilder(); FormEncodingBuilder formBuilder = new FormEncodingBuilder(); try { buildSimpleRequest(body, queryParams, headerParams, bodyBuilder, formBuilder, "", isCommon); } catch (Exception e) { throw new ApiException(e); } final String url = buildUrl(truePath, queryParams, collectionQueryParams); final Request.Builder reqBuilder = new Request.Builder().url(url); RequestBody reqBody; if (!HttpMethod.permitsRequestBody(method)) { reqBody = null; } else if ("application/x-www-form-urlencoded".equals(contentType)) { reqBody = formBuilder.build(); // fix action & version queryParams.clear(); updateQueryParams(queryParams, path.split("/")); } else if ("multipart/form-data".equals(contentType)) { reqBody = buildRequestBodyMultipart(formParams); // fix action & version queryParams.clear(); updateQueryParams(queryParams, path.split("/")); } else if (body == null) { if ("DELETE".equals(method)) { // allow calling DELETE without sending a request body reqBody = null; } else { // use an empty request body (for POST, PUT and PATCH) reqBody = RequestBody.create(MediaType.parse(contentType), ""); } // fix action & version queryParams.clear(); updateQueryParams(queryParams, path.split("/")); } else { reqBody = serialize(body, contentType); // fix action & version queryParams.clear(); updateQueryParams(queryParams, path.split("/")); } //sign final Buffer buffer = new Buffer(); try { if(reqBody != null) { reqBody.writeTo(buffer); } } catch (IOException e) { throw new ApiException(e); } updateParamsForAuth(authNames, queryParams, headerParams, serviceInfo, buffer.readUtf8()); processHeaderParams(headerParams, reqBuilder); Request request = null; if (progressRequestListener != null && reqBody != null) { ProgressRequestBody progressRequestBody = new ProgressRequestBody(reqBody, progressRequestListener); request = reqBuilder.method(method, progressRequestBody).build(); } else { request = reqBuilder.method(method, reqBody).build(); } return request; } /** * Build full URL by concatenating base path, the given sub path and query parameters. * * @param path The sub path * @param queryParams The query parameters * @param collectionQueryParams The collection query parameters * @return The full URL */ public String buildUrl(String path, List queryParams, List collectionQueryParams) { final StringBuilder url = new StringBuilder(); if (disableSSL) { url.append("http://"); } else { url.append("https://"); } url.append(endpoint).append(path); if (queryParams != null && !queryParams.isEmpty()) { // support (constant) query string in `path`, e.g. "/posts?draft=1" String prefix = path.contains("?") ? "&" : "?"; for (Pair param : queryParams) { if (param.getValue() != null) { if (prefix != null) { url.append(prefix); prefix = null; } else { url.append("&"); } String value = parameterToString(param.getValue()); url.append(escapeString(param.getName())).append("=").append(escapeString(value)); } } } if (collectionQueryParams != null && !collectionQueryParams.isEmpty()) { String prefix = url.toString().contains("?") ? "&" : "?"; for (Pair param : collectionQueryParams) { if (param.getValue() != null) { if (prefix != null) { url.append(prefix); prefix = null; } else { url.append("&"); } String value = parameterToString(param.getValue()); // collection query parameter value already escaped as part of parameterToPairs url.append(escapeString(param.getName())).append("=").append(value); } } } return url.toString(); } /** * Set header parameters to the request builder, including default headers. * * @param headerParams Header parameters in the ofrm of Map * @param reqBuilder Reqeust.Builder */ public void processHeaderParams(Map headerParams, Request.Builder reqBuilder) { for (Entry param : headerParams.entrySet()) { reqBuilder.header(param.getKey(), parameterToString(param.getValue())); } for (Entry header : defaultHeaderMap.entrySet()) { if (!headerParams.containsKey(header.getKey())) { reqBuilder.header(header.getKey(), parameterToString(header.getValue())); } } } /** * Update query and header parameters based on authentication settings. * * @param authNames The authentications to apply * @param queryParams List of query parameters * @param headerParams Map of header parameters */ public void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams) { for (String authName : authNames) { Authentication auth = authentications.get(authName); if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); auth.applyToParams(queryParams, headerParams, ""); } } public void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams, ServiceInfo serviceInfo, String payload) { for (String authName : authNames) { Authentication auth = authentications.get(authName); if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); if (auth instanceof VolcstackSign) { VolcstackSign volcengineSign = (VolcstackSign) auth; if (volcengineSign.getCredentials() == null) { throw new RuntimeException("Credentials must set when ApiClient init"); } if (StringUtils.isEmpty(credentials.getAccessKey()) || StringUtils.isEmpty(credentials.getSecretKey())) { throw new RuntimeException("AccessKey and SecretKey must set when ApiClient init Credentials"); } if (StringUtils.isEmpty(volcengineSign.getRegion())) { throw new RuntimeException("Region must set when ApiClient init"); } volcengineSign.setMethod(serviceInfo.getMethod().toUpperCase()); volcengineSign.setService(serviceInfo.getServiceName()); } auth.applyToParams(queryParams, headerParams, payload); } } /** * Build a form-encoding request body with the given form parameters. * * @param formParams Form parameters in the form of Map * @return RequestBody */ public RequestBody buildRequestBodyFormEncoding(Map formParams) { FormEncodingBuilder formBuilder = new FormEncodingBuilder(); for (Entry param : formParams.entrySet()) { formBuilder.add(param.getKey(), parameterToString(param.getValue())); } return formBuilder.build(); } /** * Build a multipart (file uploading) request body with the given form parameters, * which could contain text fields and file fields. * * @param formParams Form parameters in the form of Map * @return RequestBody */ public RequestBody buildRequestBodyMultipart(Map formParams) { MultipartBuilder mpBuilder = new MultipartBuilder().type(MultipartBuilder.FORM); for (Entry param : formParams.entrySet()) { if (param.getValue() instanceof File) { File file = (File) param.getValue(); Headers partHeaders = Headers.of("Content-Disposition", "form-data; name=\"" + param.getKey() + "\"; filename=\"" + file.getName() + "\""); MediaType mediaType = MediaType.parse(guessContentTypeFromFile(file)); mpBuilder.addPart(partHeaders, RequestBody.create(mediaType, file)); } else { Headers partHeaders = Headers.of("Content-Disposition", "form-data; name=\"" + param.getKey() + "\""); mpBuilder.addPart(partHeaders, RequestBody.create(null, parameterToString(param.getValue()))); } } return mpBuilder.build(); } /** * Guess Content-Type header from the given file (defaults to "application/octet-stream"). * * @param file The given file * @return The guessed Content-Type */ public String guessContentTypeFromFile(File file) { String contentType = URLConnection.guessContentTypeFromName(file.getName()); if (contentType == null) { return "application/octet-stream"; } else { return contentType; } } /** * Apply SSL related settings to httpClient according to the current values of * verifyingSsl and sslCaCert. */ private void applySslSettings() { try { TrustManager[] trustManagers = null; HostnameVerifier hostnameVerifier = null; if (!verifyingSsl) { TrustManager trustAll = new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public X509Certificate[] getAcceptedIssuers() { return null; } }; SSLContext sslContext = SSLContext.getInstance("TLS"); trustManagers = new TrustManager[]{trustAll}; hostnameVerifier = new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }; } else if (sslCaCert != null) { char[] password = null; // Any password will work. CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); Collection certificates = certificateFactory.generateCertificates(sslCaCert); if (certificates.isEmpty()) { throw new IllegalArgumentException("expected non-empty set of trusted certificates"); } KeyStore caKeyStore = newEmptyKeyStore(password); int index = 0; for (Certificate certificate : certificates) { String certificateAlias = "ca" + Integer.toString(index++); caKeyStore.setCertificateEntry(certificateAlias, certificate); } TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(caKeyStore); trustManagers = trustManagerFactory.getTrustManagers(); } if (keyManagers != null || trustManagers != null) { SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(keyManagers, trustManagers, new SecureRandom()); httpClient.setSslSocketFactory(sslContext.getSocketFactory()); } else { httpClient.setSslSocketFactory(null); } httpClient.setHostnameVerifier(hostnameVerifier); } catch (GeneralSecurityException e) { throw new RuntimeException(e); } } private KeyStore newEmptyKeyStore(char[] password) throws GeneralSecurityException { try { KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null, password); return keyStore; } catch (IOException e) { throw new AssertionError(e); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy