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

com.cybermkd.client.HttpClientConnection Maven / Gradle / Ivy

package com.cybermkd.client;

import com.cybermkd.client.exception.ClientException;
import com.cybermkd.common.http.ContentType;
import com.cybermkd.common.http.HttpMethod;
import com.cybermkd.common.util.stream.DefaultFileRenamer;
import com.cybermkd.common.util.stream.FileRenamer;
import com.cybermkd.log.Logger;

import javax.net.ssl.*;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.*;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Map;
import java.util.Random;

/**
 * Created by wangrenhui on 15/1/10.
 */
public class HttpClientConnection {
    private static final Logger logger = Logger.getLogger(HttpClientConnection.class);
    private final SSLSocketFactory sslSocketFactory = initSSLSocketFactory();
    private final TrustAnyHostnameVerifier trustAnyHostnameVerifier = new TrustAnyHostnameVerifier();
    protected HttpClientRequest loginRequest;
    protected ThreadLocal clientRequestTL = new ThreadLocal();
    protected CookieManager cookieManager = new CookieManager();
    protected String apiUrl;
    protected FileRenamer renamer = new DefaultFileRenamer();

    protected HttpClientConnection(String apiUrl) {
        this(apiUrl, null);
    }

    protected HttpClientConnection(String apiUrl, HttpClientRequest loginRequest) {
        this(apiUrl, loginRequest, null);
    }

    protected HttpClientConnection(String apiUrl, HttpClientRequest loginRequest, HttpClientRequest httpClientRequest) {
        this.apiUrl = apiUrl;
        this.loginRequest = loginRequest;
        if (httpClientRequest != null) {
            this.clientRequestTL.set(httpClientRequest);
        } else {
            this.clientRequestTL.set(new HttpClientRequest());
        }
        //add cookieManager
        cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
        CookieHandler.setDefault(cookieManager);
    }

    public static String getRandomString(int length) { //length表示生成字符串的长度
        String base = "abcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    /**
     * 文件重命名工具
     *
     * @param renamer 重命名工具
     */
    public void setRenamer(FileRenamer renamer) {
        if (renamer == null) {
            throw new ClientException("FileRenamer must not null.");
        }
        this.renamer = renamer;
    }

    private SSLSocketFactory initSSLSocketFactory() {
        try {
            TrustManager[] tm = {new TrustAnyTrustManager()};
            SSLContext sslContext = SSLContext.getInstance("TLS", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            return sslContext.getSocketFactory();
        } catch (Exception e) {
            throw new ClientException(e.getMessage(), e);
        }
    }

    /**
     * 获取Connection
     *
     * @param httpMethod
     * @return
     * @throws IOException
     * @throws NoSuchAlgorithmException
     * @throws NoSuchProviderException
     * @throws KeyManagementException
     */
    protected HttpURLConnection getHttpConnection(String httpMethod) throws IOException, NoSuchAlgorithmException, NoSuchProviderException, KeyManagementException {
        HttpClientRequest httpClientRequest = clientRequestTL.get();

        URL url = null;
        HttpURLConnection conn = null;

        String contentType = httpClientRequest.getContentType();
        //json请求
        if (contentType.contains(ContentType.JSON.value())) {
            // 除了post意外其他请求类型都用 拼接参数方式
            if (httpMethod.equals(HttpMethod.GET) || httpMethod.equals(HttpMethod.DELETE)) {
                if (!"".equals(httpClientRequest.getJsonParam())) {
                    url = new URL(apiUrl + httpClientRequest.getEncodedRestPath() + "?" + httpClientRequest.getEncodedJsonParam());
                } else {
                    url = new URL(apiUrl + httpClientRequest.getEncodedRestPath());
                }
                conn = openHttpURLConnection(url, httpClientRequest, httpMethod);
            } else {
                conn = getStreamConnection(httpMethod, httpClientRequest);
                outputParam(conn, httpMethod, httpClientRequest.getJsonParam(), httpClientRequest.getEncoding());
            }
        } else if (contentType.contains(ContentType.MULTIPART.value()) || httpMethod.equals(HttpMethod.POST)) {
            //上传文件类型
            conn = getStreamConnection(httpMethod, httpClientRequest);
            //是上传文件
            Map uploadFiles = httpClientRequest.getUploadFiles();
            if (uploadFiles != null && uploadFiles.size() > 0) {
                String boundary = "---------------------------" + getRandomString(13); //boundary就是request头和上传文件内容的分隔符
                conn.setRequestProperty("Content-Type", contentType + "boundary=" + boundary);

                // params
                Map params = httpClientRequest.getParams();

                DataOutputStream writer = new DataOutputStream(conn.getOutputStream());
                if (params != null && params.size() > 0) {
                    StringBuilder builder = new StringBuilder();

                    String value = null;
                    for (String key : params.keySet()) {
                        value = params.get(key);
                        if (value == null) continue;
                        builder.append("\r\n").append("--").append(boundary).append("\r\n");
                        builder.append("Content-Disposition: form-data; name=\"").append(key).append("\"\r\n\r\n");
                        builder.append(value);
                    }
                    writer.write(builder.toString().getBytes());
                }
                //上传文件
                writeUploadFiles(boundary, uploadFiles, writer);

                byte[] endData = ("\r\n--" + boundary + "--\r\n").getBytes();
                writer.write(endData);
                writer.flush();
                writer.close();
            } else {
                outputParam(conn, httpMethod, httpClientRequest.getEncodedParams(), httpClientRequest.getEncoding());
            }
        } else {
            url = new URL(apiUrl + httpClientRequest.getEncodedUrl());
            conn = openHttpURLConnection(url, httpClientRequest, httpMethod);
        }

        //ssl判断
        if (conn instanceof HttpsURLConnection) {
            ((HttpsURLConnection) conn).setSSLSocketFactory(sslSocketFactory);
            ((HttpsURLConnection) conn).setHostnameVerifier(trustAnyHostnameVerifier);
        }

        conn.setConnectTimeout(httpClientRequest.getConnectTimeOut());
        conn.setReadTimeout(httpClientRequest.getReadTimeOut());
        return conn;
    }

    /**
     * outConnection
     *
     * @param httpMethod
     * @param httpClientRequest
     * @return
     * @throws IOException
     */
    private HttpURLConnection getStreamConnection(String httpMethod, HttpClientRequest httpClientRequest) throws IOException {
        URL url;
        HttpURLConnection conn;
        url = new URL(apiUrl + httpClientRequest.getEncodedRestPath());
        conn = openHttpURLConnection(url, httpClientRequest, httpMethod);

        conn.setDoOutput(true);
        conn.setUseCaches(false);
        return conn;
    }

    /**
     * 输出参数
     *
     * @param conn
     * @param method
     * @param requestParams
     * @throws IOException
     */
    private void outputParam(HttpURLConnection conn, String method, String requestParams, String encoding) throws IOException {
        //写入参数
        if (requestParams != null && !"".equals(requestParams)) {
            DataOutputStream writer = new DataOutputStream(conn.getOutputStream());
            logger.debug("Request out method " + method + ",out parameters " + requestParams);

            writer.write(requestParams.getBytes(encoding));
            writer.flush();
            writer.close();
        }
    }

    /**
     * 写入文件到  服务器
     *
     * @param boundary    分隔符
     * @param uploadFiles 文件集合
     * @param writer      写入对象
     * @throws IOException
     */
    private void writeUploadFiles(String boundary, Map uploadFiles, DataOutputStream writer) throws IOException {
        // file
        HttpClientFile httpClientFile;
        for (String key : uploadFiles.keySet()) {
            httpClientFile = uploadFiles.get(key);
            if (httpClientFile == null) continue;

            writer.write(("\r\n" + "--" + boundary + "\r\n" + "Content-Disposition: form-data; name=\"" + key + "\"; filename=\"" + httpClientFile.getName() + "\"\r\n" + "Content-Type:" + httpClientFile.getContentType() + "\r\n\r\n").getBytes());

            DataInputStream in = new DataInputStream(httpClientFile.getInputStream());
            int bytes = 0;
            byte[] bufferOut = new byte[1024];
            while ((bytes = in.read(bufferOut)) != -1) {
                writer.write(bufferOut, 0, bytes);
            }
            in.close();
        }
    }

    /**
     * open a  Connection
     *
     * @param url    url
     * @param method method
     * @return
     * @throws IOException
     */
    private HttpURLConnection openHttpURLConnection(URL url, HttpClientRequest httpClientRequest, String method) throws IOException {
        logger.info("Open connection for api " + url.getPath());

        HttpURLConnection.setFollowRedirects(true);
        HttpURLConnection conn;
        conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod(method);

        String downloadFile = httpClientRequest.getDownloadFile();
        if (downloadFile != null) {
            File file = new File(downloadFile);
            if (file.exists()) {
                //设置下载区间
                conn.setRequestProperty("RANGE", "bytes=" + file.length() + "-");
            }
        }
        Map headers = httpClientRequest.getHeaders();
        if (headers != null && !headers.isEmpty()) {
            for (Map.Entry entry : headers.entrySet()) {
                conn.setRequestProperty(entry.getKey(), entry.getValue());
            }
        }
        logger.info("Hold cookie: %s.", cookieManager.getCookieStore().getCookies());
        conn.setRequestProperty("Content-Type", httpClientRequest.getContentType());
        conn.setRequestProperty("User-Agent", httpClientRequest.getUserAgent());
        return conn;
    }

    /**
     * https 域名校验
     */
    private class TrustAnyHostnameVerifier implements HostnameVerifier {
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    }

    /**
     * https 证书管理
     */
    private class TrustAnyTrustManager implements X509TrustManager {
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
        }

        public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
        }
    }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy