<不可读> 用于 100000 字节或以上的 POST 正文长度,同样适用于 blob/FormData
Posted
技术标签:
【中文标题】<不可读> 用于 100000 字节或以上的 POST 正文长度,同样适用于 blob/FormData【英文标题】:<Unreadable> for POST body length of 100000 bytes or above, also with blob/FormData 【发布时间】:2021-06-15 05:38:29 【问题描述】:编辑: eis 是对的,有一个干扰 (Netbeans) 调试器。
客户端向 Spring Boot servlet 发送一些数据:
fetch("/command",
method: 'POST',
cache: 'no-cache',
headers:
'Content-Type': 'application/json'
,
body: JSON.stringify(...)
);
在服务器端,HttpServletRequest.getReader()
返回一个字符串<Unreadable>
(这个拼写完全正确,没有任何其他错误或异常),而不是客户端发送的 JSON 字符串。 'Content-Type': 'text/plain; charset=UTF-8'
的情况完全相同。 JSON 字符串大约有 150kB,乍一看,在发送之前记录到浏览器的控制台,看起来像一个单行 JSON 字符串。
对于测试,我发送了几 kB 文本字段的内容,而不是 JSON 字符串。这一次,服务器收到了一个相同的字符串,没有任何问题。由于某种原因,只能发送 JSON 字符串。我测试了限制它的大小是否有帮助。事实证明,这很有效:
body: JSON.stringify(...).substring(0,99999)
但这没有:
body: JSON.stringify(...).substring(0,100000)
以下内容:
body: new Blob( [ contentsCallback().substring(0, N) ], type: 'application/json' )
适用于 N
const formData = new FormData();
formData.append('blob', new Blob( [ JSON.stringify(...).substring(0, N) ], type: 'application/json' ), 'test');
...
body: formData
适用于 N
似乎某处有大小限制。我不知道它是在客户端还是服务器端。这是服务器application.properties
的片段,我在其中放置了讨论的各种属性here:
multipart.max-file-size=20MB
multipart.max-request-size=20MB
spring.servlet.multipart.max-file-size=20MB
spring.servlet.multipart.max-request-size=20MB
multipart.maxFileSize=20Mb
multipart.maxRequestSize=20Mb
server.tomcat.max-http-post-size=10000000
server.tomcat.max-http-post-size=100000000
server.tomcat.max-swallow-size=100000000
这是 servlet 的注册方式:
@Bean
public ServletRegistrationBean commandRegistration()
ServletRegistrationBean bean = new ServletRegistrationBean(
new CommandServlet(), "/command");
// final int SIZE_LIMIT = 20000000;
// MultipartConfigElement mc = new MultipartConfigElement(TMP_FOLDER,
// SIZE_LIMIT, SIZE_LIMIT * 2, SIZE_LIMIT / 2);
// bean.setMultipartConfig(mc);
return bean;
取消注释已注释部分不会更改相关限制。
这是 fetch() 的 Chrome 数据,它发送完整的 150kB JSON(接收为 <Unreadable>
):
Request URL: https://localhost:8443/?command=save
Request Method: POST
Status Code: 200
Remote Address: [::1]:8443
Referrer Policy: strict-origin-when-cross-origin
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Connection: keep-alive
Content-Length: 0
Content-Type: text/html;charset=UTF-8
Date: Thu, 18 Mar 2021 09:32:00 GMT
Expires: 0
Keep-Alive: timeout=60
Pragma: no-cache
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,pl;q=0.8,de;q=0.7,fr;q=0.6,ru;q=0.5,es;q=0.4,nl;q=0.3,cs;q=0.2,it;q=0.1,nb;q=0.1
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 146111
Content-Type: application/json
Cookie: JSESSIONID=961B41156DCF6F7C57455AA871525198; JSESSIONID=72CCDD7A91C48660B9DD01041F4BEFBB
Host: localhost:8443
Origin: https://localhost:8443
Pragma: no-cache
Referer: https://localhost:8443/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.193 Safari/537.36
command: save
控制台日志中既没有错误也没有警告。使用 Firefox 或将 HTTP 服务器从 Tomcat 切换到 Jetty 时也会出现限制。
最后,我在所有源代码和所有 jars(包括本地 Maven 存储库中的依赖项)中搜索了 <Unreadable>
。那里找不到字符串。
这个限制可以提高吗?如何使用 POST 方法向 SpringBoot 应用程序发送大字符串? These answers 建议 POST 的实际限制远大于 100kB。
【问题讨论】:
根据提供的输出,您在本地主机上操作,对吗?什么样的操作系统?您是否有可能需要绕过一些流氓防病毒、*** 或防火墙系统? 我发现唯一能输出<unreadable>
的工具是gdb调试器...所以你没有任何调试工具干扰你的软件?
应用程序侦听https://localhost:8443
,浏览器(Chrome 或 FIrefox)在同一个本地系统上。该系统是 Linux Mint,Ubuntu 18.04 的衍生版本。我从来没有在这里安装过防病毒软件或 ***,甚至没有重新配置 iptables,但谁知道呢。
@eis 它是<Unreadable>
,即以大写字母开头。
我找到了那种 MITM。它是 Netbeans 的调试器,无法显示大于相关限制的字符串。非常感谢您的帮助,这暗示了原因可能与网络编程无关。有趣的是@eis 在另一个调试器中找到了<unreadable>
。这两个应用程序之间可能存在某种(文化)依赖关系。
【参考方案1】:
评论者怀疑有什么干扰。其中一个提示是调试器,因为 gdb 使用类似的消息,只是不以大写字母开头。事实上,这条消息(伪装成一个真实的变量值)是在 Netbeans/JPDA/JVM 调试链中的某个地方产生的。
【讨论】:
以上是关于<不可读> 用于 100000 字节或以上的 POST 正文长度,同样适用于 blob/FormData的主要内容,如果未能解决你的问题,请参考以下文章
成功将文件上传到MySQL中的字节数组,但是下载时内容不可读
如何表示一个数组 [100000][100000] 在 C++ 中只存储 0 或 1? [关闭]