
cn.gnux.core.utils.http.HttpUtil Maven / Gradle / Ivy
The newest version!
package cn.gnux.core.utils.http;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;
import cn.gnux.core.utils.CollectionUtil;
import cn.gnux.core.utils.FileUtil;
import cn.gnux.core.utils.IoUtil;
import cn.gnux.core.utils.ReUtil;
import cn.gnux.core.utils.StrUtil;
import cn.gnux.core.utils.exceptions.UtilException;
/**
* Http请求工具类
*
* @author
*/
public class HttpUtil {
public final static Pattern CHARSET_PATTERN = Pattern.compile("charset=(.*?)\"");
/**
* 编码字符为 application/x-www-form-urlencoded
*
* @param content 被编码内容
* @return 编码后的字符
*/
public static String encode(String content, String charset) {
if (StrUtil.isBlank(content)) return content;
String encodeContent = null;
try {
encodeContent = URLEncoder.encode(content, charset);
} catch (UnsupportedEncodingException e) {
throw new UtilException(StrUtil.format("Unsupported encoding: [{}]", charset), e);
}
return encodeContent;
}
/**
* 解码application/x-www-form-urlencoded字符
*
* @param content 被编码内容
* @return 编码后的字符
*/
public static String decode(String content, String charset) {
if (StrUtil.isBlank(content)) return content;
String encodeContnt = null;
try {
encodeContnt = URLDecoder.decode(content, charset);
} catch (UnsupportedEncodingException e) {
throw new UtilException(StrUtil.format("Unsupported encoding: [{}]", charset), e);
}
return encodeContnt;
}
/**
* 获取客户端IP
* 默认检测的Header:
* 1、X-Forwarded-For
* 2、X-Real-IP
* 3、Proxy-Client-IP
* 4、WL-Proxy-Client-IP
* otherHeaderNames参数用于自定义检测的Header
*
* @param request 请求对象
* @param otherHeaderNames 其他自定义头文件
* @return IP地址
*/
public static String getClientIP(javax.servlet.http.HttpServletRequest request, String... otherHeaderNames) {
String[] headers = new String[]{"X-Forwarded-For", "X-Real-IP", "Proxy-Client-IP", "WL-Proxy-Client-IP"};
if(CollectionUtil.isNotEmpty(otherHeaderNames)){
headers = CollectionUtil.addAll(headers, otherHeaderNames);
}
String ip;
for (String header : headers) {
ip = request.getHeader(header);
if(false == isUnknow(ip)){
return getMultistageReverseProxyIp(ip);
}
}
ip = request.getRemoteAddr();
return getMultistageReverseProxyIp(ip);
}
/**
* 检测是否https
* @param url URL
* @return 是否https
*/
public static boolean isHttps(String url) {
return url.toLowerCase().startsWith("https");
}
/**
* 发送get请求
*
* @param urlString 网址
* @param customCharset 自定义请求字符集,如果字符集获取不到,使用此字符集
* @return 返回内容,如果只检查状态码,正常只返回 "",不正常返回 null
* @throws IOException
*/
public static String get(String urlString, String customCharset) throws IOException {
return HttpRequest.get(urlString).charset(customCharset).execute().body();
}
/**
* 发送get请求
*
* @param urlString 网址
* @return 返回内容,如果只检查状态码,正常只返回 "",不正常返回 null
* @throws IOException
*/
public static String get(String urlString) throws IOException {
return HttpRequest.get(urlString).execute().body();
}
/**
* 发送post请求
*
* @param urlString 网址
* @param paramMap post表单数据
* @return 返回数据
* @throws IOException
*/
public static String post(String urlString, Map paramMap) throws IOException {
return HttpRequest.post(urlString).form(paramMap).execute().body();
}
/**
* 发送post请求
*
* @param urlString 网址
* @param params post表单数据
* @return 返回数据
* @throws IOException
*/
public static String post(String urlString, String params) throws IOException {
return HttpRequest.post(urlString).body(params).execute().body();
}
/**
* 获得远程String
*
* @param url 请求的url
* @param customCharset 自定义的字符集
* @return 文本
* @throws IOException
*/
public static String downloadString(String url, String customCharset) throws IOException {
InputStream in = null;
try {
in = new URL(url).openStream();
return IoUtil.read(in, customCharset);
} finally {
FileUtil.close(in);
}
}
/**
* 获得远程String
*
* @param url 请求的url
* @param destFile 目标文件
* @return 文件大小
* @throws IOException
*/
public static int downloadFile(String url, File destFile) throws IOException {
InputStream in = null;
OutputStream out = null;
try {
in = new URL(url).openStream();
out = FileUtil.getOutputStream(destFile);
return IoUtil.copy(in, out);
} finally {
FileUtil.close(in);
FileUtil.close(out);
}
}
/**
* 将Map形式的Form表单数据转换为Url参数形式
*
* @param paramMap 表单数据
* @return url参数
*/
public static String toParams(Map paramMap) {
if(CollectionUtil.isEmpty(paramMap)){
return StrUtil.EMPTY;
}
return CollectionUtil.join(paramMap.entrySet(), "&");
}
/**
* 将Map形式的Form表单数据转换为Url参数形式
* 编码键和值对
*
* @param paramMap 表单数据
* @param charset 编码
* @return url参数
*/
public static String toParams(Map paramMap, String charset) {
if(CollectionUtil.isEmpty(paramMap)){
return StrUtil.EMPTY;
}
StringBuilder sb = new StringBuilder();
boolean isFirst = true;
for (Entry item : paramMap.entrySet()) {
if (isFirst) {
isFirst = false;
} else {
sb.append("&");
}
sb.append(encode(item.getKey(), charset)).append("=").append(encode(item.getValue().toString(), charset));
}
return sb.toString();
}
/**
* 将URL参数解析为Map(也可以解析Post中的键值对参数)
* @param paramsStr 参数字符串(或者带参数的Path)
* @param charset 字符集
* @return 参数Map
*/
public static Map> decodeParams(String paramsStr, String charset) {
if (StrUtil.isBlank(paramsStr)) {
return Collections.emptyMap();
}
// 去掉Path部分
int pathEndPos = paramsStr.indexOf('?');
if (pathEndPos > 0) {
paramsStr = StrUtil.subSuf(paramsStr, pathEndPos + 1);
}
paramsStr = decode(paramsStr, charset);
final Map> params = new LinkedHashMap>();
String name = null;
int pos = 0; // 未处理字符开始位置
int i; // 未处理字符结束位置
char c; // 当前字符
for (i = 0; i < paramsStr.length(); i++) {
c = paramsStr.charAt(i);
if (c == '=' && name == null) { // 键值对的分界点
if (pos != i) {
name = paramsStr.substring(pos, i);
}
pos = i + 1;
} else if (c == '&' || c == ';') { // 参数对的分界点
if (name == null && pos != i) {
// 对于像&a&这类无参数值的字符串,我们将name为a的值设为""
addParam(params, paramsStr.substring(pos, i), StrUtil.EMPTY);
} else if (name != null) {
addParam(params, name, paramsStr.substring(pos, i));
name = null;
}
pos = i + 1;
}
}
if (pos != i) {
if (name == null) {
addParam(params, paramsStr.substring(pos, i), StrUtil.EMPTY);
} else {
addParam(params, name, paramsStr.substring(pos, i));
}
} else if (name != null) {
addParam(params, name, StrUtil.EMPTY);
}
return params;
}
/**
* 将表单数据加到URL中(用于GET表单提交)
* @param url URL
* @param form 表单数据
* @return 合成后的URL
*/
public static String urlWithForm(String url, Map form) {
final String queryString = toParams(form);
return urlWithForm(url, queryString);
}
/**
* 将表单数据字符串加到URL中(用于GET表单提交)
* @param url URL
* @param queryString 表单数据字符串
* @return 拼接后的字符串
*/
public static String urlWithForm(String url, String queryString) {
if(StrUtil.isNotBlank(queryString)){
if(url.contains("?")) {
//原URL已经带参数
url += "&" + queryString;
}
url += url.endsWith("?") ? queryString : "?" + queryString;
}
return url;
}
/**
* 从Http连接的头信息中获得字符集
*
* @param conn HTTP连接对象
* @return 字符集
*/
public static String getCharset(HttpURLConnection conn) {
if(conn == null){
return null;
}
String charset = conn.getContentEncoding();
if (StrUtil.isBlank(charset)) {
charset = ReUtil.get(CHARSET_PATTERN, conn.getContentType(), 1);
}
return charset;
}
/**
* 从多级反向代理中获得第一个非unknown IP地址
* @param ip 获得的IP地址
* @return 第一个非unknown IP地址
*/
public static String getMultistageReverseProxyIp(String ip){
// 多级反向代理检测
if (ip != null && ip.indexOf(",") > 0) {
final String[] ips = ip.trim().split(",");
for (String subIp : ips) {
if(false == isUnknow(subIp)){
ip = subIp;
break;
}
}
}
return ip;
}
/**
* 检测给定字符串是否为未知,多用于检测HTTP请求相关
*
* @param checkString 被检测的字符串
* @return 是否未知
*/
public static boolean isUnknow(String checkString) {
return StrUtil.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString);
}
/**
* 从流中读取内容
*
* @param in 输入流
* @param charset 字符集
* @return 内容
* @throws IOException
*/
@SuppressWarnings("resource")
public static String getString(InputStream in, String charset, boolean isGetCharsetFromContent) throws IOException {
if(false == isGetCharsetFromContent){
return IoUtil.read(in, charset);
}
StringBuilder content = new StringBuilder(); // 存储返回的内容
// 从返回的内容中读取所需内容
BufferedReader reader = IoUtil.getReader(in, charset);
String line = null;
while ((line = reader.readLine()) != null) {
content.append(line).append('\n');
String charsetInContent = ReUtil.get(CHARSET_PATTERN, line, 1);
if (StrUtil.isNotBlank(charsetInContent)) {
charset = charsetInContent;
reader = IoUtil.getReader(in, charset);
isGetCharsetFromContent = false;
}
}
return content.toString();
}
/**
* 根据文件扩展名获得MimeType
* @param filePath 文件路径或文件名
* @return MimeType
*/
public static String getMimeType(String filePath) {
return URLConnection.getFileNameMap().getContentTypeFor(filePath);
}
// ----------------------------------------------------------------------------------------- Private method start
/**
* 将键值对加入到值为List类型的Map中
*
* @param params 参数
* @param name key
* @param value value
* @return 是否成功
*/
private static boolean addParam(Map> params, String name, String value) {
List values = params.get(name);
if (values == null) {
values = new ArrayList(1); // 一般是一个参数
params.put(name, values);
}
values.add(value);
return true;
}
// ----------------------------------------------------------------------------------------- Private method start end
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy