This commit is contained in:
Looly 2021-08-16 22:33:30 +08:00
parent f288c497b8
commit 3fe722554c
6 changed files with 84 additions and 34 deletions

View File

@ -11,6 +11,7 @@
*
### 🐞Bug修复
* 【extra 】 修复TinyPinyinEngine空构造造成可能的误判问题
* 【http 】 修复在gzip模式下Content-Length服务端设置异常导致的阶段
-------------------------------------------------------------------------------------------------------------

View File

@ -22,6 +22,9 @@ public class FastByteArrayOutputStream extends OutputStream {
private final FastByteBuffer buffer;
/**
* 构造
*/
public FastByteArrayOutputStream() {
this(1024);
}

View File

@ -40,10 +40,13 @@ public class FastByteBuffer {
private final int minChunkLen;
public FastByteBuffer() {
this.minChunkLen = 1024;
this(1024);
}
public FastByteBuffer(int size) {
if(size <= 0){
size = 1024;
}
this.minChunkLen = Math.abs(size);
}
@ -282,4 +285,4 @@ public class FastByteBuffer {
}
}
}
}

View File

@ -102,7 +102,7 @@ public class IoUtil extends NioUtil {
* @return 传输的byte数
* @throws IORuntimeException IO异常
*/
public static long copy(Reader reader, Writer writer, int bufferSize, int count, StreamProgress streamProgress) throws IORuntimeException {
public static long copy(Reader reader, Writer writer, int bufferSize, long count, StreamProgress streamProgress) throws IORuntimeException {
return new ReaderWriterCopier(bufferSize, count, streamProgress).copy(reader, writer);
}
@ -157,7 +157,7 @@ public class IoUtil extends NioUtil {
* @throws IORuntimeException IO异常
* @since 5.7.8
*/
public static long copy(InputStream in, OutputStream out, int bufferSize, int count, StreamProgress streamProgress) throws IORuntimeException {
public static long copy(InputStream in, OutputStream out, int bufferSize, long count, StreamProgress streamProgress) throws IORuntimeException {
return new StreamCopier(bufferSize, count, streamProgress).copy(in, out);
}

View File

@ -117,6 +117,26 @@ public class HttpResponse extends HttpBase<HttpResponse> implements Closeable {
return header(Header.CONTENT_ENCODING);
}
/**
* 获取内容长度以下情况长度无效
* <ul>
* <li>Transfer-Encoding: Chunked</li>
* <li>Content-Encoding: XXX</li>
* </ul>
* 参考https://blog.csdn.net/jiang7701037/article/details/86304302
*
* @return 长度-1表示服务端未返回或长度无效
* @since 5.7.9
*/
public long contentLength() {
long contentLength = Convert.toLong(header(Header.CONTENT_LENGTH), -1L);
if (contentLength > 0 && (isChunked() || StrUtil.isNotBlank(contentEncoding()))) {
//按照HTTP协议规范 Transfer-Encoding和Content-Encoding设置后 Content-Length 无效
contentLength = -1;
}
return contentLength;
}
/**
* 是否为gzip压缩过的内容
*
@ -254,9 +274,9 @@ public class HttpResponse extends HttpBase<HttpResponse> implements Closeable {
if (null == out) {
throw new NullPointerException("[out] is null!");
}
final int contentLength = Convert.toInt(header(Header.CONTENT_LENGTH), -1);
final long contentLength = contentLength();
try {
return IoUtil.copyByNIO(bodyStream(), out, IoUtil.DEFAULT_BUFFER_SIZE, contentLength, streamProgress);
return copyBody(bodyStream(), out, contentLength, streamProgress);
} finally {
IoUtil.close(this);
if (isCloseOut) {
@ -452,33 +472,6 @@ public class HttpResponse extends HttpBase<HttpResponse> implements Closeable {
return this.isAsync ? this : forceSync();
}
/**
* 读取主体忽略EOFException异常
*
* @param in 输入流
* @throws IORuntimeException IO异常
*/
private void readBody(InputStream in) throws IORuntimeException {
if (ignoreBody) {
return;
}
final int contentLength = Convert.toInt(header(Header.CONTENT_LENGTH), -1);
final FastByteArrayOutputStream out = contentLength > 0 ?
new FastByteArrayOutputStream(contentLength) : new FastByteArrayOutputStream();
try {
IoUtil.copy(in, out, -1, contentLength, null);
} catch (IORuntimeException e) {
//noinspection StatementWithEmptyBody
if (e.getCause() instanceof EOFException || StrUtil.containsIgnoreCase(e.getMessage(), "Premature EOF")) {
// 忽略读取HTTP流中的EOF错误
} else {
throw e;
}
}
this.bodyBytes = out.toByteArray();
}
/**
* 强制同步用于初始化<br>
* 强制同步后变化如下
@ -512,6 +505,53 @@ public class HttpResponse extends HttpBase<HttpResponse> implements Closeable {
return this;
}
/**
* 读取主体忽略EOFException异常
*
* @param in 输入流
* @throws IORuntimeException IO异常
*/
private void readBody(InputStream in) throws IORuntimeException {
if (ignoreBody) {
return;
}
final long contentLength = contentLength();
final FastByteArrayOutputStream out = new FastByteArrayOutputStream((int)contentLength);
copyBody(in, out, contentLength, null);
this.bodyBytes = out.toByteArray();
}
/**
* 将响应内容写出到{@link OutputStream}<br>
* 异步模式下直接读取Http流写出同步模式下将存储在内存中的响应内容写出<br>
* 写出后会关闭Http流异步模式
*
* @param in 输入流
* @param out 写出的流
* @param contentLength 总长度-1表示未知
* @param streamProgress 进度显示接口通过实现此接口显示下载进度
* @return 拷贝长度
*/
private static long copyBody(InputStream in, OutputStream out, long contentLength, StreamProgress streamProgress) {
if (null == out) {
throw new NullPointerException("[out] is null!");
}
long copyLength = -1;
try {
copyLength = IoUtil.copy(in, out, IoUtil.DEFAULT_BUFFER_SIZE, contentLength, streamProgress);
} catch (IORuntimeException e) {
//noinspection StatementWithEmptyBody
if (e.getCause() instanceof EOFException || StrUtil.containsIgnoreCase(e.getMessage(), "Premature EOF")) {
// 忽略读取HTTP流中的EOF错误
} else {
throw e;
}
}
return copyLength;
}
/**
* 从Content-Disposition头中获取文件名
*

View File

@ -19,7 +19,9 @@ public class HttpUtilTest {
@Test
@Ignore
public void postTest() {
String result = HttpUtil.createPost("api.uhaozu.com/goods/description/1120448506").charset(CharsetUtil.UTF_8).execute().body();
String result = HttpUtil.createPost("api.uhaozu.com/goods/description/1120448506")
.charset(CharsetUtil.UTF_8)
.execute().body();
Console.log(result);
}
@ -45,6 +47,7 @@ public class HttpUtilTest {
@Test
@Ignore
public void getTest2() {
// 此链接较为特殊User-Agent去掉后进入一个JS跳转页面如果设置了需要开启302跳转
// 自定义的默认header无效
String result = HttpRequest
.get("https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=101457313&redirect_uri=http%3A%2F%2Fwww.benmovip.com%2Fpay-cloud%2Fqqlogin%2FgetCode&state=ok")