HttpClient Socks Proxy

需要用到国外的服务,但是由于帝国防火墙的原因,所以想到用 proxy,做了一个相当拙劣的封装

HttpClient Socks Proxy
package com.plumtree.hem_ctl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.HashMap;
import java.util.Map;

import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.config.RequestConfig.Builder;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.HttpContext;

public class HttpUtil {

    private HttpClientBuilder httpClientBuilder = HttpClients.custom();
    private CloseableHttpClient httpClient = null;

    private Builder requestConfigBuilder = null;
    private RequestConfig requestConfig = null;

    private RequestBuilder requestBuilder = null;
    private HttpRequestBase request = null;

    private HttpResponse httpResponse = null;

    private boolean useProxy = false;

    private String proxyHost = "127.0.0.1";
    private int proxyPort = 7070;

    public HttpUtil(String requestUri, String requestMethod) {
        requestConfigBuilder = RequestConfig.custom();
        requestBuilder = RequestBuilder.create(requestMethod);
        requestBuilder.setUri(requestUri);
    }

    public HttpUtil setRequestHeader(String name, String value) {
        requestBuilder.addHeader(name, value);
        return this;
    }

    public HttpUtil setRquestHeaders(HashMap<String, String> headers) {
        for (Map.Entry<String, String> entry : headers.entrySet()) {
            requestBuilder.addHeader(entry.getKey(), entry.getValue());
        }

        return this;
    }

    public HttpUtil setRquestParameter(String name, String value) {
        requestBuilder.addParameter(name, value);
        return this;
    }

    public HttpUtil setRequestParamters(HashMap<String, String> paramters) {
        for (Map.Entry<String, String> entry : paramters.entrySet()) {
            requestBuilder.addParameter(entry.getKey(), entry.getValue());
        }

        return this;
    }

    /**
     * 因为只想用本地的 socket5 代理, 所以不需要输入 host, 只要提供本地 socket5 代理的端口即可
     * 
     * @param port
     *            本地 socket5 代理端口
     * @return
     */
    public HttpUtil setRequestProxy(int port) {
        useProxy = true;
        proxyPort = port;

        Registry<ConnectionSocketFactory> reg = RegistryBuilder
                .<ConnectionSocketFactory> create()
                .register("http", new LocalConnectionSocket()).build();

        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(
                reg);

        cm.setMaxTotal(5);

        httpClientBuilder.setConnectionManager(cm);

        return this;
    }

    public RequestConfig getRequestConfig() {
        if (requestConfig == null)
            requestConfig = requestConfigBuilder.build();

        return requestConfig;
    }

    public HttpRequestBase getRequest() {
        if (request == null) {
            request = (HttpRequestBase) requestBuilder.build();
            request.setConfig(requestConfig);
        }

        return request;
    }

    public void execute() throws IOException, ClientProtocolException {
        close();
        httpClient = httpClientBuilder.build();
        if (useProxy) {
            InetSocketAddress socksaddr = new InetSocketAddress(proxyHost,
                    proxyPort);
            HttpClientContext context = HttpClientContext.create();
            context.setAttribute("socks.address", socksaddr);

            httpResponse = httpClient.execute(getRequest(), context);
        } else {
            httpResponse = httpClient.execute(getRequest());
        }
    }

    public Header getResponseHeader(String headerName) {
        if (httpResponse != null) {
            Header[] headers = httpResponse.getAllHeaders();

            for (Header header : headers) {
                if (header.getName().equals(headerName))
                    return header;
            }
        }

        return null;
    }

    public Header[] getResponseHeaders() {
        return httpResponse != null ? httpResponse.getAllHeaders() : null;
    }

    public HttpResponse getHttpResponse() {
        return httpResponse;
    }

    public String getHttpResponseAsString(String charset) throws IOException {
        charset = (charset == null || charset.isEmpty()) ? "UTF-8" : charset;

        InputStream in = getHttpResponse().getEntity().getContent();
        BufferedReader reader = new BufferedReader(new InputStreamReader(in,
                charset));

        StringBuffer sBuffer = new StringBuffer();
        String line = null;

        while ((line = reader.readLine()) != null) {
            sBuffer.append(line);
        }

        return sBuffer.toString();
    }

    public void close() throws IOException {
        if (httpClient != null) {
            httpClient.close();
            httpResponse = null;
        }
    }

    private static class LocalConnectionSocket implements
            ConnectionSocketFactory {
        public Socket createSocket(final HttpContext context)
                throws IOException {
            InetSocketAddress socksaddr = (InetSocketAddress) context
                    .getAttribute("socks.address");
            Proxy proxy = new Proxy(Proxy.Type.SOCKS, socksaddr);
            return new Socket(proxy);
        }

        public Socket connectSocket(final int connectTimeout,
                final Socket socket, final HttpHost host,
                final InetSocketAddress remoteAddress,
                final InetSocketAddress localAddress, final HttpContext context)
                throws IOException, ConnectTimeoutException {
            Socket sock;
            if (socket != null) {
                sock = socket;
            } else {
                sock = createSocket(context);
            }
            if (localAddress != null) {
                sock.bind(localAddress);
            }
            try {
                sock.connect(remoteAddress, connectTimeout);
            } catch (SocketTimeoutException ex) {
                throw new ConnectTimeoutException(ex, host,
                        remoteAddress.getAddress());
            }
            return sock;
        }
    }
}
HttpClient Socks Proxy

简单的测试了下:

HttpClient Socks Proxy
 1 try {
 2     HttpUtil httpUtil = new HttpUtil("http://www.ip.cn/", "GET");
 3     httpUtil.setRequestProxy(7070);
 4     httpUtil.execute();
 5 
 6     for (Header header : httpUtil.getResponseHeaders()) {
 7         System.out
 8                 .println(header.getName() + " : " + header.getValue());
 9     }
10 
11     System.out.println(httpUtil.getHttpResponseAsString(null));
12 
13     httpUtil.close();
14 } catch (Exception e) {
15     e.printStackTrace();
16 }
HttpClient Socks Proxy

HttpClient Socks Proxy

上一篇:流年似水,终无言


下一篇:信号之可重入函数