mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-07-21 15:09:48 +08:00
add HttpInputStream
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
* 【core】 强化ExceptionUtil(issue#459@Github)
|
||||
* 【core】 增强日期工具类(pr#455@Github)
|
||||
* 【setting】 构造Setting增加默认字符编码
|
||||
* 【extra】 ServletUtil增加getHeaderMap方法
|
||||
|
||||
### Bug修复
|
||||
* 【cache】 修复missCount规则(issue#465@Github)
|
||||
|
@@ -55,10 +55,10 @@ public class WatchMonitor extends Thread implements Closeable, Serializable{
|
||||
public static final WatchEvent.Kind<?> ENTRY_DELETE = StandardWatchEventKinds.ENTRY_DELETE;
|
||||
/** 全部事件 */
|
||||
public static final WatchEvent.Kind<?>[] EVENTS_ALL = {//
|
||||
StandardWatchEventKinds.OVERFLOW, //事件丢失
|
||||
StandardWatchEventKinds.ENTRY_MODIFY, //修改
|
||||
StandardWatchEventKinds.ENTRY_CREATE, //创建
|
||||
StandardWatchEventKinds.ENTRY_DELETE //删除
|
||||
OVERFLOW, //事件丢失
|
||||
ENTRY_MODIFY, //修改
|
||||
ENTRY_CREATE, //创建
|
||||
ENTRY_DELETE //删除
|
||||
};
|
||||
|
||||
/** 监听路径,必须为目录 */
|
||||
|
@@ -5,9 +5,9 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Enumeration;
|
||||
@@ -267,6 +267,27 @@ public class ServletUtil {
|
||||
}
|
||||
|
||||
// --------------------------------------------------------- Header start
|
||||
/**
|
||||
* 获取请求所有的头(header)信息
|
||||
*
|
||||
* @param request 请求对象{@link HttpServletRequest}
|
||||
* @return header值
|
||||
* @since 4.6.2
|
||||
*/
|
||||
public static Map<String, String> getHeaderMap(HttpServletRequest request) {
|
||||
final Map<String, String> headerMap = new HashMap<>();
|
||||
|
||||
final Enumeration<String> names = request.getHeaderNames();
|
||||
String name = null;
|
||||
while (names.hasMoreElements()) {
|
||||
name = names.nextElement();
|
||||
headerMap.put(name, request.getHeader(name));
|
||||
}
|
||||
|
||||
return headerMap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 忽略大小写获得请求header中的信息
|
||||
*
|
||||
@@ -274,8 +295,8 @@ public class ServletUtil {
|
||||
* @param nameIgnoreCase 忽略大小写头信息的KEY
|
||||
* @return header值
|
||||
*/
|
||||
public final static String getHeaderIgnoreCase(HttpServletRequest request, String nameIgnoreCase) {
|
||||
Enumeration<String> names = request.getHeaderNames();
|
||||
public static String getHeaderIgnoreCase(HttpServletRequest request, String nameIgnoreCase) {
|
||||
final Enumeration<String> names = request.getHeaderNames();
|
||||
String name = null;
|
||||
while (names.hasMoreElements()) {
|
||||
name = names.nextElement();
|
||||
@@ -286,6 +307,18 @@ public class ServletUtil {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得请求header中的信息
|
||||
*
|
||||
* @param request 请求对象{@link HttpServletRequest}
|
||||
* @param name 头信息的KEY
|
||||
* @param charsetName 字符集
|
||||
* @return header值
|
||||
*/
|
||||
public static String getHeader(HttpServletRequest request, String name, String charsetName) {
|
||||
return getHeader(request, name, CharsetUtil.charset(charsetName));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得请求header中的信息
|
||||
@@ -294,15 +327,12 @@ public class ServletUtil {
|
||||
* @param name 头信息的KEY
|
||||
* @param charset 字符集
|
||||
* @return header值
|
||||
* @since 4.6.2
|
||||
*/
|
||||
public final static String getHeader(HttpServletRequest request, String name, String charset) {
|
||||
public static String getHeader(HttpServletRequest request, String name, Charset charset) {
|
||||
final String header = request.getHeader(name);
|
||||
if (null != header) {
|
||||
try {
|
||||
return new String(header.getBytes(CharsetUtil.ISO_8859_1), charset);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new UtilException(StrUtil.format("Error charset {} for http request header.", charset));
|
||||
}
|
||||
return CharsetUtil.convert(header, CharsetUtil.CHARSET_ISO_8859_1, charset);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -375,7 +405,7 @@ public class ServletUtil {
|
||||
* @param name cookie名
|
||||
* @return Cookie对象
|
||||
*/
|
||||
public final static Cookie getCookie(HttpServletRequest httpServletRequest, String name) {
|
||||
public static Cookie getCookie(HttpServletRequest httpServletRequest, String name) {
|
||||
final Map<String, Cookie> cookieMap = readCookieMap(httpServletRequest);
|
||||
return cookieMap == null ? null : cookieMap.get(name);
|
||||
}
|
||||
@@ -386,7 +416,7 @@ public class ServletUtil {
|
||||
* @param httpServletRequest {@link HttpServletRequest}
|
||||
* @return Cookie map
|
||||
*/
|
||||
public final static Map<String, Cookie> readCookieMap(HttpServletRequest httpServletRequest) {
|
||||
public static Map<String, Cookie> readCookieMap(HttpServletRequest httpServletRequest) {
|
||||
Map<String, Cookie> cookieMap = new HashMap<String, Cookie>();
|
||||
Cookie[] cookies = httpServletRequest.getCookies();
|
||||
if (null == cookies) {
|
||||
@@ -404,7 +434,7 @@ public class ServletUtil {
|
||||
* @param response 响应对象{@link HttpServletResponse}
|
||||
* @param cookie Servlet Cookie对象
|
||||
*/
|
||||
public final static void addCookie(HttpServletResponse response, Cookie cookie) {
|
||||
public static void addCookie(HttpServletResponse response, Cookie cookie) {
|
||||
response.addCookie(cookie);
|
||||
}
|
||||
|
||||
@@ -415,7 +445,7 @@ public class ServletUtil {
|
||||
* @param name Cookie名
|
||||
* @param value Cookie值
|
||||
*/
|
||||
public final static void addCookie(HttpServletResponse response, String name, String value) {
|
||||
public static void addCookie(HttpServletResponse response, String name, String value) {
|
||||
response.addCookie(new Cookie(name, value));
|
||||
}
|
||||
|
||||
@@ -429,7 +459,7 @@ public class ServletUtil {
|
||||
* @param path Cookie的有效路径
|
||||
* @param domain the domain name within which this cookie is visible; form is according to RFC 2109
|
||||
*/
|
||||
public final static void addCookie(HttpServletResponse response, String name, String value, int maxAgeInSeconds, String path, String domain) {
|
||||
public static void addCookie(HttpServletResponse response, String name, String value, int maxAgeInSeconds, String path, String domain) {
|
||||
Cookie cookie = new Cookie(name, value);
|
||||
if (domain != null) {
|
||||
cookie.setDomain(domain);
|
||||
@@ -449,7 +479,7 @@ public class ServletUtil {
|
||||
* @param value cookie值
|
||||
* @param maxAgeInSeconds -1: 关闭浏览器清除Cookie. 0: 立即清除Cookie. >0 : Cookie存在的秒数.
|
||||
*/
|
||||
public final static void addCookie(HttpServletResponse response, String name, String value, int maxAgeInSeconds) {
|
||||
public static void addCookie(HttpServletResponse response, String name, String value, int maxAgeInSeconds) {
|
||||
addCookie(response, name, value, maxAgeInSeconds, "/", null);
|
||||
}
|
||||
|
||||
|
@@ -20,7 +20,7 @@ import cn.hutool.extra.tokenizer.TokenizerException;
|
||||
public class AnalysisEngine implements TokenizerEngine {
|
||||
|
||||
private Analyzer analyzer;
|
||||
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
|
@@ -4,8 +4,8 @@ import org.ansj.splitWord.Analysis;
|
||||
import org.ansj.splitWord.analysis.ToAnalysis;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.tokenizer.TokenizerEngine;
|
||||
import cn.hutool.extra.tokenizer.Result;
|
||||
import cn.hutool.extra.tokenizer.TokenizerEngine;
|
||||
|
||||
/**
|
||||
* Ansj分词引擎实现<br>
|
||||
@@ -38,5 +38,5 @@ public class AnsjEngine implements TokenizerEngine {
|
||||
public Result parse(CharSequence text) {
|
||||
return new AnsjResult(analysis.parseStr(StrUtil.str(text)));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -39,5 +39,5 @@ public class HanLPEngine implements TokenizerEngine {
|
||||
public Result parse(CharSequence text) {
|
||||
return new HanLPResult(this.seg.seg(StrUtil.str(text)));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -39,5 +39,4 @@ public class IKAnalyzerEngine implements TokenizerEngine {
|
||||
this.seg.reset(StrUtil.getReader(text));
|
||||
return new IKAnalyzerResult(this.seg);
|
||||
}
|
||||
|
||||
}
|
||||
|
111
hutool-http/src/main/java/cn/hutool/http/HttpInputStream.java
Normal file
111
hutool-http/src/main/java/cn/hutool/http/HttpInputStream.java
Normal file
@@ -0,0 +1,111 @@
|
||||
package cn.hutool.http;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.zip.DeflaterInputStream;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
/**
|
||||
* HTTP输入流,此流用于包装Http请求响应内容的流,用于解析各种压缩、分段的响应流内容
|
||||
*
|
||||
* @author Looly
|
||||
*
|
||||
*/
|
||||
public class HttpInputStream extends InputStream {
|
||||
|
||||
/** 原始流 */
|
||||
private volatile InputStream in;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param response 响应对象
|
||||
*/
|
||||
public HttpInputStream(HttpResponse response) {
|
||||
init(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return this.in.read();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
return this.in.read(b, off, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long skip(long n) throws IOException {
|
||||
return this.in.skip(n);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
return this.in.available();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
this.in.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void mark(int readlimit) {
|
||||
this.in.mark(readlimit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void reset() throws IOException {
|
||||
this.in.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean markSupported() {
|
||||
return this.in.markSupported();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化流
|
||||
*
|
||||
* @param response 响应对象
|
||||
*/
|
||||
private void init(HttpResponse response) {
|
||||
try {
|
||||
this.in = (response.status < HttpStatus.HTTP_BAD_REQUEST) ? response.httpConnection.getInputStream() : response.httpConnection.getErrorStream();
|
||||
} catch (IOException e) {
|
||||
if (e instanceof FileNotFoundException) {
|
||||
// 服务器无返回内容,忽略之
|
||||
} else {
|
||||
throw new HttpException(e);
|
||||
}
|
||||
}
|
||||
|
||||
// 在一些情况下,返回的流为null,此时提供状态码说明
|
||||
if (null == this.in) {
|
||||
this.in = new ByteArrayInputStream(StrUtil.format("Error request, response status: {}", response.status).getBytes());
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO 分段响应内容解析
|
||||
if(response.isChunked()) {
|
||||
}
|
||||
|
||||
if (response.isGzip() && false == (response.in instanceof GZIPInputStream)) {
|
||||
// Accept-Encoding: gzip
|
||||
try {
|
||||
this.in = new GZIPInputStream(this.in);
|
||||
} catch (IOException e) {
|
||||
// 在类似于Head等方法中无body返回,此时GZIPInputStream构造会出现错误,在此忽略此错误读取普通数据
|
||||
// ignore
|
||||
}
|
||||
} else if (response.isDeflate() && false == (this.in instanceof DeflaterInputStream)) {
|
||||
// Accept-Encoding: defalte
|
||||
this.in = new DeflaterInputStream(this.in);
|
||||
}
|
||||
}
|
||||
}
|
@@ -12,8 +12,6 @@ import java.net.HttpCookie;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.zip.DeflaterInputStream;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.io.FastByteArrayOutputStream;
|
||||
@@ -38,13 +36,13 @@ import cn.hutool.log.StaticLog;
|
||||
public class HttpResponse extends HttpBase<HttpResponse> implements Closeable {
|
||||
|
||||
/** 持有连接对象 */
|
||||
private HttpConnection httpConnection;
|
||||
protected HttpConnection httpConnection;
|
||||
/** Http请求原始流 */
|
||||
private InputStream in;
|
||||
protected InputStream in;
|
||||
/** 是否异步,异步下只持有流,否则将在初始化时直接读取body内容 */
|
||||
private volatile boolean isAsync;
|
||||
/** 响应状态码 */
|
||||
private int status;
|
||||
protected int status;
|
||||
/** 是否忽略读取Http响应体 */
|
||||
private boolean ignoreBody;
|
||||
/** 从响应中获取的编码 */
|
||||
@@ -373,9 +371,9 @@ public class HttpResponse extends HttpBase<HttpResponse> implements Closeable {
|
||||
* @throws HttpException IO异常
|
||||
*/
|
||||
private HttpResponse init() throws HttpException {
|
||||
// 获取响应状态码
|
||||
try {
|
||||
this.status = httpConnection.responseCode();
|
||||
this.in = (this.status < HttpStatus.HTTP_BAD_REQUEST) ? this.httpConnection.getInputStream() : this.httpConnection.getErrorStream();
|
||||
} catch (IOException e) {
|
||||
if (e instanceof FileNotFoundException) {
|
||||
// 服务器无返回内容,忽略之
|
||||
@@ -394,31 +392,15 @@ public class HttpResponse extends HttpBase<HttpResponse> implements Closeable {
|
||||
// 存储服务端设置的Cookie信息
|
||||
GlobalCookieManager.store(httpConnection);
|
||||
|
||||
// 获取响应编码
|
||||
final Charset charset = httpConnection.getCharset();
|
||||
this.charsetFromResponse = charset;
|
||||
if (null != charset) {
|
||||
this.charset = charset;
|
||||
}
|
||||
|
||||
if (null == this.in) {
|
||||
// 在一些情况下,返回的流为null,此时提供状态码说明
|
||||
this.in = new ByteArrayInputStream(StrUtil.format("Error request, response status: {}", this.status).getBytes());
|
||||
} else {
|
||||
// TODO 分段响应内容解析
|
||||
|
||||
if (isGzip() && false == (in instanceof GZIPInputStream)) {
|
||||
// Accept-Encoding: gzip
|
||||
try {
|
||||
in = new GZIPInputStream(in);
|
||||
} catch (IOException e) {
|
||||
// 在类似于Head等方法中无body返回,此时GZIPInputStream构造会出现错误,在此忽略此错误读取普通数据
|
||||
// ignore
|
||||
}
|
||||
} else if (isDeflate() && false == (in instanceof DeflaterInputStream)) {
|
||||
// Accept-Encoding: defalte
|
||||
in = new DeflaterInputStream(in);
|
||||
}
|
||||
}
|
||||
// 获取响应内容流
|
||||
this.in = new HttpInputStream(this);
|
||||
|
||||
// 同步情况下强制同步
|
||||
return this.isAsync ? this : forceSync();
|
||||
|
@@ -63,7 +63,8 @@ public class HttpUtilTest {
|
||||
@Test
|
||||
@Ignore
|
||||
public void getTest5() {
|
||||
String res = HttpUtil.get("https://comment.bilibili.com/67573272.xml");
|
||||
String res = HttpRequest.get("https://comment.bilibili.com/67573272.xml")
|
||||
.execute().body();
|
||||
Console.log(res);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user