JDK版本: openjdk_8_201
hutool版本: 5.8.8(请确保最新尝试是否还有问题)
合作的第三方对外提供了一个http接口,使用postman可以访问并能正常返回结果,使用hutool httputil 线程一直卡死
等待在那里,后通过tcp客户端进行模拟,抓包的内容如下,模拟步骤如下,我本地起了一个8883的tcpserver,然后运下方hutool代码,建立http连接, 发送上述POSTMAN成功返回体内容, hutool工具一直卡死等待,一直等到我这边服务端手动断开连接之后, hutool才把内容打印出来,而使用postman访问模拟的tcpserver时,tcpserver发送完成之后,连接就自动关闭了,并且postman客户端能正常返回json内容,使用apache client 也能正常访问,使用jdk原生HttpURLConnection对象也会出现同样的问题,给人的感觉是服务端的问题,服务端是c++编写比较简陋,且代码不可见,但使用postman就能访问,不知道问题出在哪,能否通过在客户端设置)一些参数解决该问题。
POSTMAN 请求体
GET /api/test/testGetWithBodyParam HTTP/1.1
Content-Type: application/json
User-Agent: PostmanRuntime/7.26.8
Accept: /
Postman-Token: cc1818a7-a983-4340-a3a8-8e3bff55f196
Host: 127.0.0.1:8883
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 15
{"name" :"aaa"}
返回体
HTTP/1.1 200 Request is completed
Content-Type : application/json;charset=utf-8
Cache-Control : no-cache
Connection : close
Content-Length : 34
{"taskID": 370, "flightID" : 2879}
复现代码
JSONObject jsonObject2 = new JSONObject();
jsonObject2.putOpt("name", "370");
String body2 = HttpRequest.get("http://127.0.0.1:8883/api/test/testGetWithBodyParam").
body(JSONUtil.toJsonStr(jsonObject2)).
execute().body();
System.out.println(body2);
堆栈信息
测试涉及到的文件(注意脱密)
使用tcp工具模拟截图 https://foruda.gitee.com/images/1666072677292275454/694fb8cc_682663.jpeg
postman访问可以正常返回,hutool访问卡死 需要手动在服务端关闭连接,才能读到内容。
不好复现。
大概率是服务端的问题。
你先设置超时时间:
String body2 = HttpRequest.get("http://127.0.0.1:8883/api/test/testGetWithBodyParam")
//设置超时时间
.timeout(2000)
.body(JSONUtil.toJsonStr(jsonObject2))
execute().body();
已经试过了,设置超时时间后,到达超时时间后连接断开,报读超时异常,可以复现,用tcp工具开启一个server,hutool进行发送,上面有个模拟的截图
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
又测试了一下,不知道是不是这个原因,先说现象,hutool httputil 中似乎并没有对服务端响应报文中的Connection字段进行处理,无论是close,还是keep-alive,在处理完返回体之后
连接都是一直处于活动的状态(通过tcp模拟工具进行观察),这个时候线程一直处于挂起状态,即使设置了超时时间,也会报读超时异常,然后我又在tcp模拟工具中把该连接关闭,此hutool挂起的线程继续执行,就可以打出了返回体的内容,猜测hutool 一但在服务器端发送完响应报文时候没有主动关闭连接,就会出现该问题,
实际上这步应该在客户端解析完 Connection的值后进行断开连接处理(结论是通过apache client进行得出 下面贴出模拟的图)
//测试代码
Map<String, Object> map = new HashMap<>();
map.put("taskID", 370);
map.put("flightID", 2879);
//-------------------------------使用apache client 进行访问-----------------------//
//创建httpclient对象
CloseableHttpClient client = HttpClients.createDefault();
HttpGetWithEntity httpGetWithEntity = new HttpGetWithEntity("http://127.0.0.1:8884/api/test/testHttpUtilGetWithBody");
HttpEntity httpEntity = new StringEntity(JSONUtil.toJsonStr(map), ContentType.APPLICATION_JSON);
httpGetWithEntity.setEntity(httpEntity);
//执行请求操作,并拿到结果(同步阻塞)
CloseableHttpResponse response = client.execute(httpGetWithEntity);
//获取结果实体
HttpEntity entity = response.getEntity();
if (entity != null) {
//按指定编码转换结果实体为String类型
String body = EntityUtils.toString(entity, "utf-8");
System.out.println("Apache client客户端请求返回结果:" + body);
}
//释放链接
response.close();
//防止函数执行完成之后,main方法退出,导致连接退出
while (true){
ThreadUtil.safeSleep(1);
}
//-------------------------------使用apache client 进行访问-----------------------//
//-------------------------------使用hutool 进行访问-----------------------//
String body = HttpRequest.get("http://127.0.0.1:8884/api/test/testHttpUtilGetWithBody").body(JSONUtil.toJsonStr(map)).execute().body();
System.out.println("使用hutool返回结果:" + body);
//-------------------------------使用hutool 进行访问-----------------------//
@Looly uyong关联的 Pull Request !845:#I5WAV4 修复http请求读取响应时堵塞问题 刚试了一下 并不解决这个问题
@sony_7 经过测试,应该是你的响应报文格式不规范造成的(Postman和HttpClient应该是做了一定的容错)
你的头信息中header部分键值对部分:
两边不应该加空格:
HTTP/1.1 200 Request is completed
Content-Type:application/json;charset=utf-8
Cache-Control:no-cache
Connection:close
Content-Length:34
{"taskID": 370, "flightID" : 2879}
这样就正常返回了。
如有问题可继续打开此issue讨论。
登录 后才可以发表评论