<不可读> 用于 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() 返回一个字符串&lt;Unreadable&gt;(这个拼写完全正确,没有任何其他错误或异常),而不是客户端发送的 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(接收为 &lt;Unreadable&gt;):

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 存储库中的依赖项)中搜索了 &lt;Unreadable&gt;。那里找不到字符串。

这个限制可以提高吗?如何使用 POST 方法向 SpringBoot 应用程序发送大字符串? These answers 建议 POST 的实际限制远大于 100kB。

【问题讨论】:

根据提供的输出,您在本地主机上操作,对吗?什么样的操作系统?您是否有可能需要绕过一些流氓防病毒、*** 或防火墙系统? 我发现唯一能输出&lt;unreadable&gt;的工具是gdb调试器...所以你没有任何调试工具干扰你的软件? 应用程序侦听https://localhost:8443,浏览器(Chrome 或 FIrefox)在同一个本地系统上。该系统是 Linux Mint,Ubuntu 18.04 的衍生版本。我从来没有在这里安装过防病毒软件或 ***,甚至没有重新配置 iptables,但谁知道呢。 @eis 它是&lt;Unreadable&gt;,即以大写字母开头。 我找到了那种 MITM。它是 Netbeans 的调试器,无法显示大于相关限制的字符串。非常感谢您的帮助,这暗示了原因可能与网络编程无关。有趣的是@eis 在另一个调试器中找到了&lt;unreadable&gt;。这两个应用程序之间可能存在某种(文化)依赖关系。 【参考方案1】:

评论者怀疑有什么干扰。其中一个提示是调试器,因为 gdb 使用类似的消息,只是不以大写字母开头。事实上,这条消息(伪装成一个真实的变量值)是在 Netbeans/JPDA/JVM 调试链中的某个地方产生的。

【讨论】:

以上是关于<不可读> 用于 100000 字节或以上的 POST 正文长度,同样适用于 blob/FormData的主要内容,如果未能解决你的问题,请参考以下文章

成功将文件上传到MySQL中的字节数组,但是下载时内容不可读

如何表示一个数组 [100000][100000] 在 C++ 中只存储 0 或 1? [关闭]

使用 Logback 的日志中不可读的线程名称

从/向FIFO读/写

csharp 用于以人类可读方式表示任意字节长度的实用程序。

c++/c语言求助 string变量作为结构体成员在引用的时候内存不可读的问题