一次与玄学的战争(革命已成功)

2017-02-03 12:58 #旧文章

相信各位读者中一定有遇到过玄学的,玄学是什么?别问我。

今晚在制作图片上传功能的时候,就遇到了一个让我百思不得其解的玄学。

在文件上传中有这么一句代码 request.getPart("sessionID");,这是用来验证用户身份的,又因为是文件上传,使用的请求格式是 multi-part,所以只能用 getPart()来获取参数。在官方文档中提到了可能抛出的异常,其中一个是

IllegalStateException – if the request body is larger than maxRequestSize, or any Part in the request is larger than maxFileSize

而在 getPart()所在 trycatch 中,IllegalStateException 是不被要求捕获的,所以一旦上传文件大小超出了设置的极限,tomcat 就会进入 500 界面。而我想在 IllegalStateException 发生的时候将其捕获,好了,这下玄学出现了,如果我捕获了这个异常,则在浏览器上会发现产生了 net::ERR_CONNECTION_RESET。WTF!

目前我还在摸索,不知道该怎么解决。如果有哪位大神知道解决方案,那麻烦请戳下面的 QQ 联系我。

好了,我已经知道怎么解决这个玄学了。

测试所在的环境

  • Chrome 56.0.2924.67 Beta
  • Kubuntu 15.10
  • Tomcat 7 8

万分无奈的我选择了使用 WireShark 进行 TCP 层面上的审查,结果我发现了如下的情况

  • 我没有捕获 IllegalStateException
    1. 此时浏览器会向服务器传送大量的数据
    2. 服务器在接收数据超出了设定的范围后抛出 500 错误
    3. 浏览器继续传输大量数据直至结束
    4. 服务器发送 RST
    5. Chrome Dev Tools 显示状态为 500
  • 我捕获了 IllegalStateException 并且输出了回应
    1. 浏览器向服务器发送大量的数据
    2. 浏览器在接收数据超出了设定的范围后抛出 IllegalStateException 并被捕获,向浏览器做出回应
    3. 浏览器继续传输大量数据直至结束
    4. 服务器发送 RST
    5. Chrome Dev Tools 显示状态为 net::ERR_CONNECTION_RESET

然后我思考了两个情况的异同

  1. 两种情况在服务器都会向浏览器发送 HTTP 回应
  2. 两种情况服务器都会发送 RST
  3. 浏览器在接收到 500 状态时显示出了服务器的回应

所以我猜测是不是当状态码是 200 且在数据传送完成后服务器发送了 RST 包时,Chrome 会认为这一次数据传输是失败的。所以我尝试在对 IllegalStateException 的异常处理中将状态码设置为了 400 Bad Request,重启服务器测试,成功!

好吧,我不知到给怎么评价这一个玄学,只能说 WireShark 是解决网络错误的利器。

现在我可以上传图片了!