Looly 5 years ago
parent
commit
c9a180abce

+ 1 - 0
CHANGELOG.md

@@ -19,6 +19,7 @@
 ### Bug修复
 * 【core   】     修复CsvReader读取双引号未转义问题(issur#I2BMP1@Gitee)
 * 【json   】     JSONUtil.parse修复config无效问题(issur#1363@Github)
+* 【http   】     修复SimpleServer返回响应内容Content-Lenth不正确的问题(issur#1358@Github)
 
 -------------------------------------------------------------------------------------------------------------
 

+ 64 - 9
hutool-http/src/main/java/cn/hutool/http/server/HttpServerResponse.java

@@ -46,7 +46,7 @@ public class HttpServerResponse extends HttpServerBase {
 	}
 
 	/**
-	 * 发送HTTP状态码
+	 * 发送HTTP状态码,Content-Length为0不定长度,会输出Transfer-encoding: chunked
 	 *
 	 * @param httpStatusCode HTTP状态码,见HttpStatus
 	 * @return this
@@ -65,6 +65,17 @@ public class HttpServerResponse extends HttpServerBase {
 	}
 
 	/**
+	 * 发送成功状态码
+	 *
+	 * @param bodyLength 响应体长度,默认0表示不定长度,会输出Transfer-encoding: chunked
+	 * @return this
+	 * @since 5.5.7
+	 */
+	public HttpServerResponse sendOk(int bodyLength) {
+		return send(HttpStatus.HTTP_OK, bodyLength);
+	}
+
+	/**
 	 * 发送404错误页
 	 *
 	 * @param content 错误页页面内容,默认text/html类型
@@ -91,7 +102,7 @@ public class HttpServerResponse extends HttpServerBase {
 	 * 发送HTTP状态码
 	 *
 	 * @param httpStatusCode HTTP状态码,见HttpStatus
-	 * @param bodyLength     响应体长度,默认0
+	 * @param bodyLength     响应体长度,默认0表示不定长度,会输出Transfer-encoding: chunked
 	 * @return this
 	 */
 	public HttpServerResponse send(int httpStatusCode, long bodyLength) {
@@ -290,7 +301,8 @@ public class HttpServerResponse extends HttpServerBase {
 	 * @return this
 	 */
 	public HttpServerResponse write(byte[] data) {
-		return write(new ByteArrayInputStream(data));
+		final ByteArrayInputStream in = new ByteArrayInputStream(data);
+		return write(in, in.available());
 	}
 
 	/**
@@ -302,8 +314,21 @@ public class HttpServerResponse extends HttpServerBase {
 	 * @since 5.2.6
 	 */
 	public HttpServerResponse write(InputStream in, String contentType) {
+		return write(in, 0, contentType);
+	}
+
+	/**
+	 * 返回数据给客户端
+	 *
+	 * @param in          需要返回客户端的内容
+	 * @param length 内容长度,默认0表示不定长度,会输出Transfer-encoding: chunked
+	 * @param contentType 返回的类型
+	 * @return this
+	 * @since 5.2.7
+	 */
+	public HttpServerResponse write(InputStream in, int length, String contentType) {
 		setContentType(contentType);
-		return write(in);
+		return write(in, length);
 	}
 
 	/**
@@ -313,9 +338,23 @@ public class HttpServerResponse extends HttpServerBase {
 	 * @return this
 	 */
 	public HttpServerResponse write(InputStream in) {
+		return write(in, 0);
+	}
+
+	/**
+	 * 写出数据到客户端
+	 *
+	 * @param in     数据流
+	 * @param length 指定响应内容长度,默认0表示不定长度,会输出Transfer-encoding: chunked
+	 * @return this
+	 */
+	public HttpServerResponse write(InputStream in, int length) {
+		if (false == isSendCode) {
+			sendOk(Math.max(0, length));
+		}
 		OutputStream out = null;
 		try {
-			out = getOut();
+			out = this.httpExchange.getResponseBody();
 			IoUtil.copy(in, out);
 		} finally {
 			IoUtil.close(out);
@@ -332,12 +371,16 @@ public class HttpServerResponse extends HttpServerBase {
 	 * @since 5.2.6
 	 */
 	public HttpServerResponse write(File file) {
+		final long fileSize = file.length();
+		if(fileSize > Integer.MAX_VALUE){
+			throw new IllegalArgumentException("File size is too bigger than " + Integer.MAX_VALUE);
+		}
 		final String fileName = file.getName();
 		final String contentType = ObjectUtil.defaultIfNull(HttpUtil.getMimeType(fileName), "application/octet-stream");
 		BufferedInputStream in = null;
 		try {
 			in = FileUtil.getInputStream(file);
-			write(in, contentType, fileName);
+			write(in, (int)fileSize, contentType, fileName);
 		} finally {
 			IoUtil.close(in);
 		}
@@ -352,13 +395,25 @@ public class HttpServerResponse extends HttpServerBase {
 	 * @param fileName    文件名
 	 * @since 5.2.6
 	 */
-		public void write(InputStream in, String contentType, String fileName) {
+	public void write(InputStream in, String contentType, String fileName) {
+		write(in, 0, contentType, fileName);
+	}
+
+	/**
+	 * 返回文件数据给客户端(文件下载)
+	 *
+	 * @param in          需要返回客户端的内容
+	 * @param contentType 返回的类型
+	 * @param fileName    文件名
+	 * @since 5.2.7
+	 */
+	public HttpServerResponse write(InputStream in, int length, String contentType, String fileName) {
 		final Charset charset = ObjectUtil.defaultIfNull(this.charset, DEFAULT_CHARSET);
 
-		if(false == contentType.startsWith("text/")){
+		if (false == contentType.startsWith("text/")) {
 			// 非文本类型数据直接走下载
 			setHeader(Header.CONTENT_DISPOSITION, StrUtil.format("attachment;filename={}", URLUtil.encode(fileName, charset)));
 		}
-		write(in, contentType);
+		return write(in, length, contentType);
 	}
 }

+ 2 - 4
hutool-http/src/test/java/cn/hutool/http/server/SimpleServerTest.java

@@ -45,10 +45,8 @@ public class SimpleServerTest {
 							response.write(request.getMultipart().getParamMap().toString(), ContentType.TEXT_PLAIN.toString());
 						}
 				)
-				.addAction("test/zeroStr", (req, res)->{
-					res.addHeader("Content-Length", "0".length() + "");
-					res.write("0");
-				})
+				// 测试输出响应内容是否能正常返回Content-Length头信息
+				.addAction("test/zeroStr", (req, res)-> res.write("0"))
 				.start();
 	}
 }

+ 9 - 0
hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java

@@ -10,6 +10,7 @@ import cn.hutool.json.test.bean.UserC;
 import org.junit.Assert;
 import org.junit.Test;
 
+import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
@@ -164,6 +165,14 @@ public class JSONUtilTest {
 	}
 
 	@Test
+	public void doubleTest2() {
+		String json = "{\"test\": 12.00}";
+		final JSONObject jsonObject = JSONUtil.parseObj(json);
+		jsonObject.set("test2", new BigInteger("12"));
+		Console.log(jsonObject);
+	}
+
+	@Test
 	public void parseObjTest() {
 		// 测试转义
 		final JSONObject jsonObject = JSONUtil.parseObj("{\n" +