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

com.github.bingoohuang.utils.net.HttpReq Maven / Gradle / Ivy

There is a newer version: 0.0.25
Show newest version
package com.github.bingoohuang.utils.net;

import com.github.bingoohuang.utils.codec.Json;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocketFactory;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
import java.util.List;

public class HttpReq {
    private final String baseUrl;
    private String req;
    private StringBuilder params = new StringBuilder();
    Logger logger = LoggerFactory.getLogger(HttpReq.class);
    private List> props = Lists.newArrayList();
    private SSLSocketFactory sslSocketFactory;
    private HostnameVerifier hostnameVerifier;
    private String body;
    private String anchor;


    public HttpReq(String baseUrl) {
        this.baseUrl = baseUrl;
    }

    public static HttpReq get(String baseUrl) {
        return new HttpReq(baseUrl);
    }

    public HttpReq req(String req) {
        this.req = req;
        return this;
    }

    public HttpReq body(String body) {
        this.body = body;
        return this;
    }

    public HttpReq anchor(String anchor) {
        this.anchor = anchor;
        return this;
    }

    public HttpReq cookie(String value) {
        if (value == null) return this;

        return prop("Cookie", value);
    }

    public HttpReq prop(String name, String value) {
        props.add(Pair.of(name, value));
        return this;
    }

    public HttpReq param(String name, String value) {
        if (params.length() > 0) params.append('&');
        params.append(name).append('=').append(Url.encode(value));

        return this;
    }

    public HttpReq requestBody(String requestBody) {
        if (requestBody != null) {
            if (params.length() > 0) params.append('&');
            params.append(requestBody);
        }

        return this;
    }

    public HttpReq sslSocketFactory(SSLSocketFactory sslSocketFactory) {
        this.sslSocketFactory = sslSocketFactory;
        return this;
    }

    public HttpReq hostnameVerifier(HostnameVerifier hostnameVerifier) {
        this.hostnameVerifier = hostnameVerifier;
        return this;
    }

    public String post() {
        HttpURLConnection http = null;
        try {
            String url = baseUrl + (req == null ? "" : req)
                    + (params.length() > 0 && body != null? ("?" + params) : "")
                    + (anchor == null ? "" : "#" + anchor);

            http = commonSettings(url);
            setHeaders(http);
            postSettings(http);
            if (sslSocketFactory != null)
                ((HttpsURLConnection) http).setSSLSocketFactory(sslSocketFactory);

            if (hostnameVerifier != null)
                ((HttpsURLConnection) http).setHostnameVerifier(hostnameVerifier);

            // 连接,从postUrl.openConnection()至此的配置必须要在connect之前完成,
            // 要注意的是connection.getOutputStream会隐含的进行connect。
            http.connect();

            writePostRequestBody(http);

            return parseResponse(http, url);
        } catch (Exception e) {
            logger.error("post error {}", e.getMessage());
            return null;
        } finally {
            if (http != null) http.disconnect();
        }
    }

    private void postSettings(HttpURLConnection http) throws ProtocolException {
        // 设置是否向connection输出,因为这个是post请求,参数要放在
        // http正文内,因此需要设为true
        http.setDoOutput(true);
        http.setDoInput(true); // Read from the connection. Default is true.
        http.setRequestMethod("POST");// 默认是 GET方式
        http.setUseCaches(false); // Post 请求不能使用缓存
        http.setInstanceFollowRedirects(true);
        // 配置本次连接的Content-type,配置为application/x-www-form-urlencoded的
        // 意思是正文是urlencoded编码过的form参数,下面我们可以看到我们对正文内容使用URLEncoder.encode进行编码
        http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
    }


    public String get() {
        HttpURLConnection http = null;
        try {
            String url = baseUrl + (req == null ? "" : req)
                    + (params.length() > 0 ? ("?" + params) : "")
                    + (anchor == null ? "" : "#" + anchor);

            http = commonSettings(url);
            setHeaders(http);

            if (sslSocketFactory != null)
                ((HttpsURLConnection) http).setSSLSocketFactory(sslSocketFactory);

            if (hostnameVerifier != null)
                ((HttpsURLConnection) http).setHostnameVerifier(hostnameVerifier);

            http.connect();

            return parseResponse(http, url);
        } catch (Exception e) {
            logger.error("get error {}", e.getMessage());
            return null;
        } finally {
            if (http != null) http.disconnect();
        }
    }

    private void setHeaders(HttpURLConnection http) {
        for (Pair prop : props)
            http.setRequestProperty(prop.getKey(), prop.getValue());
    }

    private HttpURLConnection commonSettings(String url) throws IOException {
        HttpURLConnection http = (HttpURLConnection) new URL(url).openConnection();
        http.setRequestProperty("Accept-Charset", "UTF-8");
        HttpURLConnection.setFollowRedirects(true);
        http.setConnectTimeout(60 * 1000);
        http.setReadTimeout(60 * 1000);
        return http;
    }

    private void writePostRequestBody(HttpURLConnection http) throws IOException {
        if (params.length() == 0 && StringUtils.isEmpty(body)) return;

        if (StringUtils.isNotEmpty(body)) {
            OutputStreamWriter out = new OutputStreamWriter(http.getOutputStream(), "UTF-8");
            out.append(body);
            out.flush();
            out.close();
        } else {
            DataOutputStream out = new DataOutputStream(http.getOutputStream());
            // The URL-encoded contend 正文,正文内容其实跟get的URL中 '? '后的参数字符串一致
            // DataOutputStream.writeBytes将字符串中的16位的unicode字符以8位的字符形式写到流里面
            String postData = params.toString();
            out.writeBytes(postData);
            out.flush();
            out.close();
        }
    }

    private String parseResponse(HttpURLConnection http, String url) throws IOException {
        int status = http.getResponseCode();
        String charset = getCharset(http.getHeaderField("Content-Type"));

        if (status == 200) return readResponseBody(http, charset);

        logger.warn("non 200 response :" + readErrorResponseBody(url, http, status, charset));
        return null;
    }

    private String readErrorResponseBody(String url, HttpURLConnection http, int status, String charset) throws IOException {
        InputStream errorStream = http.getErrorStream();
        if (errorStream != null) {
            String error = toString(charset, errorStream);
            return (url + ", STATUS CODE =" + status + ", headers=" + Json.json(http.getHeaderFields()) + "\n\n" + error);
        } else {
            return (url + ", STATUS CODE =" + status + ", headers=" + Json.json(http.getHeaderFields()));
        }
    }

    private static String readResponseBody(HttpURLConnection http, String charset) throws IOException {
        InputStream inputStream = http.getInputStream();

        return toString(charset, inputStream);
    }

    private static String toString(String charset, InputStream inputStream) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];

        int length;
        while ((length = inputStream.read(buffer)) != -1) {
            baos.write(buffer, 0, length);
        }

        return new String(baos.toByteArray(), charset);
    }

    private static String getCharset(String contentType) {
        if (contentType == null) return "UTF-8";

        String charset = null;
        for (String param : contentType.replace(" ", "").split(";")) {
            if (param.startsWith("charset=")) {
                charset = param.split("=", 2)[1];
                break;
            }
        }

        return charset == null ? "UTF-8" : charset;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy