001/* 002 * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.mybatisflex.core.audit.http; 017 018import com.mybatisflex.core.util.StringUtil; 019import org.apache.ibatis.logging.LogFactory; 020 021import javax.net.ssl.*; 022import java.io.IOException; 023import java.io.InputStreamReader; 024import java.io.OutputStream; 025import java.io.UnsupportedEncodingException; 026import java.net.HttpURLConnection; 027import java.net.URL; 028import java.net.URLEncoder; 029import java.security.KeyManagementException; 030import java.security.NoSuchAlgorithmException; 031import java.security.NoSuchProviderException; 032import java.security.cert.CertificateException; 033import java.security.cert.X509Certificate; 034import java.util.Map; 035import java.util.Map.Entry; 036 037 038public class HttpUtil { 039 040 private HttpUtil() {} 041 042 private static final String POST = "POST"; 043 044 045 private static String CHARSET = "UTF-8"; 046 private static int connectTimeout = 15000; // 连接超时,单位毫秒 047 private static int readTimeout = 15000; // 读取超时,单位毫秒 048 049 private static final SSLSocketFactory sslSocketFactory = initSSLSocketFactory(); 050 051 private static final TrustAnyHostnameVerifier trustAnyHostnameVerifier = new TrustAnyHostnameVerifier(); 052 053 /** 054 * https 域名校验 055 */ 056 private static class TrustAnyHostnameVerifier implements HostnameVerifier { 057 @Override 058 public boolean verify(String hostname, SSLSession session) { 059 return true; 060 } 061 } 062 063 /** 064 * https 证书管理 065 */ 066 private static class TrustAnyTrustManager implements X509TrustManager { 067 @Override 068 public X509Certificate[] getAcceptedIssuers() { 069 return null; 070 } 071 072 @Override 073 public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { 074 } 075 076 @Override 077 public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { 078 } 079 } 080 081 082 private static SSLSocketFactory initSSLSocketFactory() { 083 try { 084 TrustManager[] tm = {new HttpUtil.TrustAnyTrustManager()}; 085 SSLContext sslContext = SSLContext.getInstance("TLS"); // ("TLS", "SunJSSE"); 086 sslContext.init(null, tm, new java.security.SecureRandom()); 087 return sslContext.getSocketFactory(); 088 } catch (Exception e) { 089 throw new RuntimeException(e); 090 } 091 } 092 093 public static void setCharSet(String charSet) { 094 if (StringUtil.isBlank(charSet)) { 095 throw new IllegalArgumentException("charSet can not be blank."); 096 } 097 HttpUtil.CHARSET = charSet; 098 } 099 100 public static void setConnectTimeout(int connectTimeout) { 101 HttpUtil.connectTimeout = connectTimeout; 102 } 103 104 public static void setReadTimeout(int readTimeout) { 105 HttpUtil.readTimeout = readTimeout; 106 } 107 108 private static HttpURLConnection getHttpConnection(String url, String method, Map<String, String> headers) throws IOException, NoSuchAlgorithmException, NoSuchProviderException, KeyManagementException { 109 URL _url = new URL(url); 110 HttpURLConnection conn = (HttpURLConnection) _url.openConnection(); 111 if (conn instanceof HttpsURLConnection) { 112 ((HttpsURLConnection) conn).setSSLSocketFactory(sslSocketFactory); 113 ((HttpsURLConnection) conn).setHostnameVerifier(trustAnyHostnameVerifier); 114 } 115 116 conn.setRequestMethod(method); 117 conn.setDoOutput(true); 118 conn.setDoInput(true); 119 120 conn.setConnectTimeout(connectTimeout); 121 conn.setReadTimeout(readTimeout); 122 123 conn.setRequestProperty("Content-Type", "application/json; charset=utf-8"); 124 125 if (headers != null && !headers.isEmpty()) { 126 for (Entry<String, String> entry : headers.entrySet()) { 127 conn.setRequestProperty(entry.getKey(), entry.getValue()); 128 } 129 } 130 131 return conn; 132 } 133 134 135 /** 136 * Send POST request 137 */ 138 public static String post(String url, Map<String, String> queryParas, String data, Map<String, String> headers) { 139 HttpURLConnection conn = null; 140 try { 141 conn = getHttpConnection(buildUrlQuery(url, queryParas), POST, headers); 142 conn.connect(); 143 144 if (data != null) { 145 try (OutputStream out = conn.getOutputStream()) { 146 out.write(data.getBytes(CHARSET)); 147 out.flush(); 148 } 149 } 150 return readString(conn); 151 } catch (IOException e) { 152 LogFactory.getLog(HttpUtil.class).error("post error.", e); 153 return null; 154 } catch (Exception e) { 155 throw new RuntimeException(e); 156 } finally { 157 if (conn != null) { 158 conn.disconnect(); 159 } 160 } 161 } 162 163 public static String post(String url, Map<String, String> queryParas, String data) { 164 return post(url, queryParas, data, null); 165 } 166 167 public static String post(String url, String data, Map<String, String> headers) { 168 return post(url, null, data, headers); 169 } 170 171 public static String post(String url, String data) { 172 return post(url, null, data, null); 173 } 174 175 private static String readString(HttpURLConnection conn) throws IOException { 176 try (InputStreamReader isr = new InputStreamReader(conn.getInputStream(), CHARSET)) { 177 StringBuilder ret = new StringBuilder(); 178 char[] buf = new char[1024]; 179 for (int num; (num = isr.read(buf, 0, buf.length)) != -1; ) { 180 ret.append(buf, 0, num); 181 } 182 return ret.toString(); 183 } 184 } 185 186 187 private static String buildUrlQuery(String url, Map<String, String> queryParas) { 188 if (queryParas == null || queryParas.isEmpty()) { 189 return url; 190 } 191 192 StringBuilder sb = new StringBuilder(url); 193 boolean isFirst; 194 if (url.indexOf('?') == -1) { 195 isFirst = true; 196 sb.append('?'); 197 } else { 198 isFirst = false; 199 } 200 201 for (Entry<String, String> entry : queryParas.entrySet()) { 202 if (isFirst) { 203 isFirst = false; 204 } else { 205 sb.append('&'); 206 } 207 208 String key = entry.getKey(); 209 String value = entry.getValue(); 210 if (StringUtil.isNotBlank(value)) { 211 try { 212 value = URLEncoder.encode(value, CHARSET); 213 } catch (UnsupportedEncodingException e) { 214 throw new RuntimeException(e); 215 } 216 } 217 sb.append(key).append('=').append(value); 218 } 219 return sb.toString(); 220 } 221 222 223} 224 225 226 227 228 229