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

cn.schoolwow.quickhttp.handler.RequestHandler Maven / Gradle / Ivy

There is a newer version: 3.0.1
Show newest version
package cn.schoolwow.quickhttp.handler;

import cn.schoolwow.quickhttp.domain.ClientConfig;
import cn.schoolwow.quickhttp.domain.MetaWrapper;
import cn.schoolwow.quickhttp.domain.RequestMeta;
import cn.schoolwow.quickhttp.request.Request;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.HttpsURLConnection;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;

public class RequestHandler extends AbstractHandler{
    private static Logger logger = LoggerFactory.getLogger(RequestHandler.class);
    private static ThreadLocal builderThreadLocal = new ThreadLocal<>();
    private static final char[] mimeBoundaryChars =
            "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
    private static final int boundaryLength = 32;

    public RequestHandler(MetaWrapper metaWrapper) {
        super(metaWrapper);
        StringBuilder builder = builderThreadLocal.get();
        if(null==builder){
            builderThreadLocal.set(new StringBuilder());
        }
    }

    @Override
    public Handler handle() throws IOException {
        HttpURLConnection httpURLConnection = createHttpUrlConnection(metaWrapper);
        metaWrapper.responseMeta.httpURLConnection = httpURLConnection;
        return new ResponseHandler(metaWrapper);
    }

    /**
     * 创建HttpUrlConnection对象
     */
    private HttpURLConnection createHttpUrlConnection(MetaWrapper metaWrapper) throws IOException {
        RequestMeta requestMeta = metaWrapper.requestMeta;
        ClientConfig clientConfig = metaWrapper.clientConfig;

        //添加路径请求参数
        if (!requestMeta.parameterMap.isEmpty()) {
            StringBuilder parameterBuilder = builderThreadLocal.get();
            parameterBuilder.setLength(0);
            Set> entrySet = requestMeta.parameterMap.entrySet();
            for (Map.Entry entry : entrySet) {
                String value = entry.getValue();
                if (null != value) {
                    value = URLEncoder.encode(value, requestMeta.charset);
                }
                parameterBuilder.append(URLEncoder.encode(entry.getKey(), requestMeta.charset) + "=" + value + "&");
            }
            parameterBuilder.deleteCharAt(parameterBuilder.length() - 1);
            if (requestMeta.url.toString().contains("?")) {
                parameterBuilder.insert(0, "&");
            } else {
                parameterBuilder.insert(0, "?");
            }
            requestMeta.url = new URL(requestMeta.url.toString() + parameterBuilder.toString());
        }
        URL u = requestMeta.url;
        final HttpURLConnection httpURLConnection = (HttpURLConnection) (
                requestMeta.proxy == null ? u.openConnection() : u.openConnection(requestMeta.proxy)
        );
        logger.info("[请求行]{} {},代理:{}", requestMeta.method.name(), u, requestMeta.proxy == null ? "无" : requestMeta.proxy.address());
        //判断是否https
        if (httpURLConnection instanceof HttpsURLConnection) {
            ((HttpsURLConnection) httpURLConnection).setSSLSocketFactory(clientConfig.sslSocketFactory);
            ((HttpsURLConnection) httpURLConnection).setHostnameVerifier(clientConfig.hostnameVerifier);
        }
        httpURLConnection.setRequestMethod(requestMeta.method.name());
        httpURLConnection.setConnectTimeout(requestMeta.connectTimeoutMillis);
        httpURLConnection.setReadTimeout(requestMeta.readTimeoutMillis);
        httpURLConnection.setInstanceFollowRedirects(false);
        //设置头部
        {
            Set>> entrySet = requestMeta.headerMap.entrySet();
            for(Map.Entry> entry:entrySet){
                for(String value:entry.getValue()){
                    httpURLConnection.addRequestProperty(entry.getKey(), value);
                }
            }
        }
        //设置Cookie
        try {
            Map> cookieHeaderMap = clientConfig.cookieManager.get(requestMeta.url.toURI(), requestMeta.headerMap);
            if(cookieHeaderMap.containsKey("Cookie")){
                List cookieList = cookieHeaderMap.get("Cookie");
                if(cookieList.size()>0){
                    logger.trace("[设置Cookie头部]{}",cookieHeaderMap);
                    StringBuilder builder = builderThreadLocal.get();
                    builder.setLength(0);
                    for(String cookie:cookieList){
                        builder.append(" "+cookie+";");
                    }
                    httpURLConnection.setRequestProperty("Cookie",builder.toString());
                }
            }
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        //执行请求
        httpURLConnection.setDoInput(true);
        StringBuilder builder = builderThreadLocal.get();
        builder.setLength(0);
        if (requestMeta.method.hasBody() && (!requestMeta.dataFileMap.isEmpty() || null != requestMeta.requestBody || !requestMeta.dataMap.isEmpty())) {
            //优先级 dataFile > requestBody > dataMap
            if (Request.ContentType.MULTIPART_FORMDATA.equals(requestMeta.userContentType) || !requestMeta.dataFileMap.isEmpty()) {
                if (null == requestMeta.boundary) {
                    requestMeta.boundary = mimeBoundary();
                }
                httpURLConnection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + requestMeta.boundary);
                httpURLConnection.setChunkedStreamingMode(0);
                if(!requestMeta.dataFileMap.isEmpty()){
                    builder.append("[MultipartFile]" + requestMeta.dataFileMap);
                }
                if(!requestMeta.dataMap.isEmpty()){
                    builder.append("[Multipart]" + requestMeta.dataMap);
                }
            } else if (Request.ContentType.APPLICATION_JSON.equals(requestMeta.userContentType) || (requestMeta.requestBody != null && requestMeta.requestBody.length > 0)) {
                httpURLConnection.setRequestProperty("Content-Type", (requestMeta.userContentType==null?"application/json":requestMeta.userContentType) + "; charset=" + requestMeta.charset + ";");
                httpURLConnection.setFixedLengthStreamingMode(requestMeta.requestBody.length);
                builder.append(new String(requestMeta.requestBody,requestMeta.charset));
            } else if (Request.ContentType.APPLICATION_X_WWW_FORM_URLENCODED.equals(requestMeta.userContentType) || !requestMeta.dataMap.isEmpty()) {
                httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=" + requestMeta.charset);
                if (!requestMeta.dataMap.isEmpty()) {
                    StringBuilder formBuilder = new StringBuilder();
                    Set> entrySet = requestMeta.dataMap.entrySet();
                    for (Map.Entry entry : entrySet) {
                        String value = entry.getValue();
                        if (null != value) {
                            value = URLEncoder.encode(value, requestMeta.charset);
                        }
                        formBuilder.append(URLEncoder.encode(entry.getKey(), requestMeta.charset) + "=" + value + "&");
                    }
                    formBuilder.deleteCharAt(formBuilder.length() - 1);
                    requestMeta.requestBody = formBuilder.toString().getBytes(Charset.forName(requestMeta.charset));
                }
                httpURLConnection.setFixedLengthStreamingMode(requestMeta.requestBody.length);
                builder.append("[Form]"+requestMeta.dataMap.toString());
            }
            if (null != requestMeta.contentType && requestMeta.contentType.isEmpty()) {
                httpURLConnection.setRequestProperty("Content-Type", requestMeta.contentType);
            }
            //开始正式写入数据
            httpURLConnection.setDoOutput(true);
            OutputStream outputStream = httpURLConnection.getOutputStream();
            final BufferedWriter w = new BufferedWriter(new OutputStreamWriter(outputStream, requestMeta.charset));
            if (Request.ContentType.MULTIPART_FORMDATA.equals(requestMeta.userContentType) || !requestMeta.dataFileMap.isEmpty()) {
                if (!requestMeta.dataMap.isEmpty()) {
                    Set> entrySet = requestMeta.dataMap.entrySet();
                    for (Map.Entry entry : entrySet) {
                        w.write("--" + requestMeta.boundary + "\r\n");
                        w.write("Content-Disposition: form-data; name=\"" + entry.getKey().replace("\"", "%22") + "\"\r\n");
                        w.write("\r\n");
                        w.write(entry.getValue());
                        w.write("\r\n");
                    }
                }
                Set>> entrySet = requestMeta.dataFileMap.entrySet();
                for (Map.Entry> entry : entrySet) {
                    Collection pathCollection = entry.getValue();
                    for(Path file:pathCollection){
                        String name = entry.getKey().replace("\"", "%22");

                        w.write("--" + requestMeta.boundary + "\r\n");
                        w.write("Content-Disposition: form-data; name=\"" + name + "\"; filename=\"" + file.getFileName().toString().replace("\"", "%22") + "\"\r\n");
                        w.write("Content-Type: " + Files.probeContentType(file) + "\r\n");
                        w.write("\r\n");
                        w.flush();
                        outputStream.write(Files.readAllBytes(file));
                        outputStream.flush();
                        w.write("\r\n");
                    }
                }
                w.write("--" + requestMeta.boundary + "--\r\n");
            } else if (Request.ContentType.APPLICATION_JSON.equals(requestMeta.userContentType) || requestMeta.requestBody != null && !requestMeta.requestBody.equals("")) {
                outputStream.write(requestMeta.requestBody);
            } else if (Request.ContentType.APPLICATION_X_WWW_FORM_URLENCODED.equals(requestMeta.userContentType) || !requestMeta.dataMap.isEmpty()) {
                if (null != requestMeta.requestBody) {
                    outputStream.write(requestMeta.requestBody);
                }
            }
            w.flush();
            w.close();
        }
        requestMeta.bodyLog = builder.toString();
        return httpURLConnection;
    }

    /**
     * 创建随机Boundary字符串作为分隔符
     */
    private static String mimeBoundary() {
        final StringBuilder mime = new StringBuilder(boundaryLength);
        final Random rand = new Random();
        for (int i = 0; i < boundaryLength; i++) {
            mime.append(mimeBoundaryChars[rand.nextInt(mimeBoundaryChars.length)]);
        }
        return mime.toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy