package com.smtscript.utils; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpCookie; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.security.SecureRandom; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; public class HttpClient { public static interface HttpClientNotify { public void send(HttpURLConnection conn, String body); public void receive(HttpURLConnection conn, String recv); } public abstract static class HttpClientStream { public void ready(HttpURLConnection conn) throws Exception{} public void post(HttpURLConnection conn, OutputStream os) throws Exception{} public void receive(HttpURLConnection conn, InputStream is) throws Exception{} } public static class HttpClientPostFile { public String _name; public String _fileName; public InputStream _is; public HttpClientPostFile(String name, String fileName, InputStream is) { _name = name; _fileName = fileName; _is = is; } } protected static class HttpClientCookieManager { protected Object _lock = new Object(); protected Map> _mapHost2Cookie = new HashMap>(); protected String getUrlHost(URL uri) { return String.format("%s://%s:%d", uri.getProtocol(), uri.getHost(), uri.getPort()); } public Map getCookieByURL(URL url) { return _mapHost2Cookie.get(getUrlHost(url)); } public void setCookie(URL url, String[] cookies) { String uriHost = getUrlHost(url); Map mapCookies = _mapHost2Cookie.get(uriHost); if(mapCookies == null) { mapCookies = new HashMap(); _mapHost2Cookie.put(uriHost, mapCookies); } for(int i = 0; i < cookies.length; i += 2) { HttpCookie cookie = new HttpCookie(cookies[i + 0], cookies[i + 1]); mapCookies.put(cookie.getName(), cookie); } } public void get(HttpURLConnection conn) { synchronized(_lock) { URL uri = conn.getURL(); String uriHost = getUrlHost(uri); Map mapCookies = _mapHost2Cookie.get(uriHost); if(mapCookies == null) return; StringBuilder sbCookie = new StringBuilder(); for(Entry entry : mapCookies.entrySet()) { HttpCookie cookie = entry.getValue(); if((cookie.getPath() != null && !uri.getPath().startsWith(cookie.getPath())) || cookie.hasExpired()) continue; if(sbCookie.length() > 0) sbCookie.append("; "); sbCookie.append(String.format("%s=%s", cookie.getName(), cookie.getValue())); //sbCookie.append(cookie.toString()); } if(sbCookie.length() > 0) { //_logger.log(SMTLog.Debug, String.format("Get Cookie:%s=%s", uri.toString(), sbCookie.toString())); conn.setRequestProperty("Cookie", sbCookie.toString()); } } } public void put(HttpURLConnection conn) { synchronized(_lock) { URL uri = conn.getURL(); List headers = null; for(Entry> entry : conn.getHeaderFields().entrySet()) { String key = entry.getKey(); if(key != null && key.equalsIgnoreCase("set-cookie")) { headers = entry.getValue(); break; } } if(headers == null) return; String uriHost = getUrlHost(uri); Map mapCookies = _mapHost2Cookie.get(uriHost); if(mapCookies == null) { mapCookies = new HashMap(); _mapHost2Cookie.put(uriHost, mapCookies); } for(String header : headers) { for(HttpCookie cookie : HttpCookie.parse(header)) { mapCookies.put(cookie.getName(), cookie); //_logger.log(SMTLog.Debug, String.format("Set Cookie:%s=%s", uri.toString(), header)); } } mapCookies = null; } } } protected boolean _logHead = true; //protected String _encodeName = "UTF-8"; protected HttpClientCookieManager _cookieManager = new HttpClientCookieManager(); public HttpClient() { _cookieManager = new HttpClientCookieManager(); } public Map getCookies(String surl) throws Exception { URL url = new URL(surl); return _cookieManager.getCookieByURL(url); } public void setCookies(String surl, String[] cookies) throws Exception { URL url = new URL(surl); _cookieManager.setCookie(url, cookies); } /** * 用GET方式请求url,并返回字节流 * * @param url - 请求的url * @param params - 请求的参数列表(名称,值) * @param heads - 请求头的设置(名称,值) * @param out - 返回的输出流 * @throws Exception */ public void getHttpStream(String url, String[] params, String[] heads, String encodeName, final OutputStream out) throws Exception { StringBuilder sbParams = new StringBuilder(); sbParams.append(url); if(params != null && params.length > 0) { sbParams.append("?"); for(int i = 0; i < params.length; i += 2) { if(sbParams.length() > 0) sbParams.append("&"); sbParams.append(params[i + 0]); sbParams.append("="); sbParams.append(URLEncoder.encode(params[i + 1], encodeName)); } } queryHttpClient("GET", url, encodeName, new HttpClientStream(){ @Override public void receive(HttpURLConnection conn, InputStream is) throws Exception{ int size; byte[] data = new byte[10240]; while((size = is.read(data)) > 0) { out.write(data, 0, size); } } }, heads); } /** * 用GET方式请求url,并返回字符串 * * @param url - 请求的url * @param params - 请求的参数列表(名称,值) * @param heads - 请求头的设置(名称,值) * @return - 返回请求的字符串 * @throws Exception */ public String getHttpString(String url, String[] params, String[] heads, String encodeName, HttpClientNotify notify) throws Exception { return new String(getHttpBytes(url, params, heads, encodeName, notify), encodeName); } public static String encodeURIComponent(String s, String encode) throws Exception { String result = null; result = URLEncoder.encode(s, encode) .replaceAll("\\+", "%20") .replaceAll("\\%21", "!") .replaceAll("\\%27", "'") .replaceAll("\\%28", "(") .replaceAll("\\%29", ")") .replaceAll("\\%7E", "~"); return result; } public byte[] getHttpBytes(String url, String[] params, String[] heads, final String encodeName, final HttpClientNotify notify) throws Exception { StringBuilder sbParams = new StringBuilder(); sbParams.append(url); if(params != null && params.length > 0) { sbParams.append("?"); int startPos = sbParams.length(); for(int i = 0; i < params.length; i += 2) { if(sbParams.length() > startPos) sbParams.append("&"); sbParams.append(params[i + 0]); sbParams.append("="); sbParams.append(encodeURIComponent(params[i + 1], encodeName)); } } if(notify != null) notify.send(null, sbParams.toString()); final ByteArrayOutputStream bos = new ByteArrayOutputStream(); queryHttpClient("GET", sbParams.toString(), encodeName, new HttpClientStream(){ @Override public void receive(HttpURLConnection conn, InputStream is) throws Exception{ int size; byte[] data = new byte[10240]; while((size = is.read(data)) > 0) { bos.write(data, 0, size); if(notify != null) notify.receive(conn, new String(bos.toByteArray(), encodeName)); } } }, heads); return bos.toByteArray(); } /** * 用POST方式上传文件,并返回字符串 * * @param url - 请求的url * @param params - 请求的参数列表(名称,值) * @param heads - 请求头的设置(名称,值) * @param files - 要上传的文件列表 * @return - 返回请求的字符串 * @throws Exception */ public byte[] postStreamHttp(String url, final String[] params, String[] heads, final String encodeName, final HttpClientPostFile[] files) throws Exception { final ByteArrayOutputStream bos = new ByteArrayOutputStream(); final String BOUNDARY = "---------------------------" + SMTStatic.newUUID(); queryHttpClient("POST", url, encodeName, new HttpClientStream(){ @Override public void ready(HttpURLConnection conn) throws Exception{ conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY.substring(2)); } @Override public void post(HttpURLConnection conn, OutputStream os) throws Exception{ // 上传参数 if(params != null && params.length > 0) { for(int i = 0; i < params.length; i += 2) { String data = String.format( "%s\r\n" + // BOUNDARY "Content-Disposition: form-data; name=\"%s\"\r\n" + // name "\r\n" + "%s\r\n", // value BOUNDARY, params[i + 0], URLEncoder.encode(params[i + 1], encodeName) ); os.write(data.getBytes(encodeName)); } } // 上传文件 if(files != null && files.length > 0) { for(int i = 0; i < files.length; i ++) { // 发送文件提交头信息 String data = String.format( "%s\r\n" + // BOUNDARY "Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\n" + // name filename "Content-Type: application/octet-stream\r\n" + "\r\n", BOUNDARY, files[i]._name, files[i]._fileName ); os.write(data.getBytes(encodeName)); // 发送文件内容 int size; byte[] data1 = new byte[10240]; while((size = files[i]._is.read(data1)) > 0) { os.write(data1, 0, size); } // 写入换行符 os.write("\r\n".getBytes(encodeName)); } // 写入结束节 os.write(String.format("%s--", BOUNDARY).getBytes(encodeName)); } } @Override public void receive(HttpURLConnection conn, InputStream is) throws Exception{ int size; byte[] data = new byte[10240]; while((size = is.read(data)) > 0) { bos.write(data, 0, size); } } }, heads); return bos.toByteArray(); } /** * 用POST方式请求,并返回字符串 * * @param url - 请求的url * @param params - 请求的参数列表(名称,值) * @param heads - 请求头的设置(名称,值) * @return - 返回请求的字符串 * @throws Exception */ public String postHttpString(String url, String[] params, String[] heads, String encodeName, HttpClientNotify notify) throws Exception { return new String(postHttpBytes(url, params, heads, encodeName, notify), encodeName); } public byte[] postHttpBytes(String url, String[] params, String[] heads, String encodeName, HttpClientNotify notify) throws Exception { final StringBuilder sbParams = new StringBuilder(); if(params != null) { for(int i = 0; i < params.length; i += 2) { if(sbParams.length() > 0) sbParams.append("&"); sbParams.append(URLEncoder.encode(params[i + 0], encodeName)); sbParams.append("="); sbParams.append(URLEncoder.encode(params[i + 1], encodeName)); } } return postHttpBytes(url, sbParams.toString(), heads, encodeName, notify); } public byte[] postHttpBytes(String url, final String body, String[] heads, final String encodeName, final HttpClientNotify notify) throws Exception { final ByteArrayOutputStream bos = new ByteArrayOutputStream(); queryHttpClient("POST", url, encodeName, new HttpClientStream(){ @Override public void post(HttpURLConnection conn, OutputStream os) throws Exception{ if(notify != null) notify.send(conn, body); os.write(body.getBytes(encodeName)); } @Override public void receive(HttpURLConnection conn, InputStream is) throws Exception{ int size; byte[] data = new byte[10240]; while((size = is.read(data)) > 0) { bos.write(data, 0, size); if(notify != null) notify.receive(conn, new String(bos.toByteArray(), encodeName)); } if(notify != null) notify.receive(conn, null); } },heads); return bos.toByteArray(); } private static class Restful { static TrustManager[] trustAllCerts = new TrustManager[] { 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; } } }; public class NullHostNameVerifier implements HostnameVerifier { /* * (non-Javadoc) * * @see javax.net.ssl.HostnameVerifier#verify(java.lang.String, * javax.net.ssl.SSLSession) */ @Override public boolean verify(String arg0, SSLSession arg1) { return true; } } } public void queryHttpClient(String method, String surl, String encodeName, HttpClientStream notify, String[] mapHeads)throws Exception { HttpURLConnection connection = null; InputStream inputStream = null; OutputStream outputStream = null; try { HttpsURLConnection.setDefaultHostnameVerifier(new Restful().new NullHostNameVerifier()); SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, Restful.trustAllCerts, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); // 创建连接 URL url = new URL(surl); connection = (HttpURLConnection) url.openConnection(); // 针对GET的操作 if("GET".equalsIgnoreCase(method)) { // 设置cookie _cookieManager.get(connection); // 如果存在head映射表,则将其注入 if(mapHeads != null) { for(int i = 0; i < mapHeads.length; i += 2) { connection.setRequestProperty(mapHeads[i + 0], mapHeads[i + 1]); } } // 通过通知方式设定标题 if(notify != null) notify.ready(connection); connection.connect(); // 获取新的cookie _cookieManager.put(connection); } // 针对POST的操作 else if("POST".equalsIgnoreCase(method)) { // 将HTTP头发送过去 //_cookieManager.put(new URI(surl), connection.getHeaderFields()); connection.setDoOutput(true); connection.setRequestMethod("POST"); connection.setUseCaches(false); connection.setInstanceFollowRedirects(false); //connection.setRequestProperty("Content-Type", request.getHeader("Content-Type")); //connection.setRequestProperty("Content-Length", request.getHeader("Content-Length")); connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + encodeName); //connection.setRequestProperty("Content-Length", request.getHeader("Content-Length")); // 设置cookie _cookieManager.get(connection); // 如果存在head映射表,则将其注入 if(mapHeads != null) { for(int i = 0; i < mapHeads.length; i += 2) { connection.setRequestProperty(mapHeads[i + 0], mapHeads[i + 1]); } } // 通过通知方式设定标题 if(notify != null) notify.ready(connection); connection.connect(); // 将POST的信息复制到转发服务器中 outputStream = connection.getOutputStream(); // 通过通知方式上传参数 if(notify != null) notify.post(connection, outputStream); // 获取新的cookie _cookieManager.put(connection); // 关闭参数传递通道 outputStream.flush(); outputStream.close(); outputStream = null; } else throw new RuntimeException(String.format("unsupport method %s", method)); // 打开远程流读取远程信息 inputStream = connection.getInputStream(); if(notify != null) notify.receive(connection, inputStream); } finally { if(inputStream != null)inputStream.close(); if(outputStream != null)outputStream.close(); if(connection != null)connection.disconnect(); } } }