add HttpInputStream

This commit is contained in:
Looly
2019-08-16 15:04:42 +08:00
parent 6b011af032
commit 9e39667e5a
10 changed files with 174 additions and 50 deletions

View File

@@ -16,6 +16,7 @@
* 【core】 强化ExceptionUtilissue#459@Github
* 【core】 增强日期工具类pr#455@Github
* 【setting】 构造Setting增加默认字符编码
* 【extra】 ServletUtil增加getHeaderMap方法
### Bug修复
* 【cache】 修复missCount规则issue#465@Github

View File

@@ -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 //删除
};
/** 监听路径,必须为目录 */

View File

@@ -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. &gt;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);
}

View File

@@ -20,7 +20,7 @@ import cn.hutool.extra.tokenizer.TokenizerException;
public class AnalysisEngine implements TokenizerEngine {
private Analyzer analyzer;
/**
* 构造
*

View File

@@ -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)));
}
}

View File

@@ -39,5 +39,5 @@ public class HanLPEngine implements TokenizerEngine {
public Result parse(CharSequence text) {
return new HanLPResult(this.seg.seg(StrUtil.str(text)));
}
}

View File

@@ -39,5 +39,4 @@ public class IKAnalyzerEngine implements TokenizerEngine {
this.seg.reset(StrUtil.getReader(text));
return new IKAnalyzerResult(this.seg);
}
}

View 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);
}
}
}

View File

@@ -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();

View File

@@ -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);
}