‹Unreadable› для длины тела POST 100000 байт или выше, а также с blob/FormData

EDIT: он был прав, был мешающий отладчик (Netbeans).

Клиент отправляет некоторые данные сервлету Spring Boot:

        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 имеет размер около 150 КБ и на первый взгляд, зарегистрированная в консоли браузера перед отправкой, выглядит как однострочная строка JSON.

Для тестов я отправил содержимое текстового поля размером в несколько килобайт вместо строки JSON. На этот раз сервер без проблем получил идентичную строку. По какой-то причине может быть отправлена ​​только строка JSON. Я проверил, помогает ли ограничение его размера. Как оказалось, это сработало:

body: JSON.stringify(...).substring(0,99999)

но это не так:

body: JSON.stringify(...).substring(0,100000)

Следующее:

body: new Blob( [ contentsCallback().substring(0, N) ], { type: 'application/json' } )

работает за 100000р. Этот:

const formData = new FormData();
formData.append('blob', new Blob( [ JSON.stringify(...).substring(0, N) ], { type: 'application/json' } ), 'test');
...
body: formData

работает для N‹99823.

Похоже, где-то есть ограничение по размеру. Я не знаю, на стороне клиента или на стороне сервера. Это фрагмент сервера application.properties, где я поместил различные свойства, обсуждаемые здесь :

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

Вот как регистрируется сервлет:

@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;
}

Раскомментирование закомментированной части не меняет рассматриваемый предел.

Вот данные Chrome для fetch(), которая отправляет полные 150 КБ 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.

Наконец, я просмотрел все исходники и все jar-файлы (включая зависимости в локальном репозитории Maven) на наличие <Unreadable>. Строка не может быть найдена там.

Можно ли увеличить этот лимит? Как отправить большую строку в приложение SpringBoot с помощью метода POST? Эти ответы предполагают, что практические ограничения для POST намного превышают 100 КБ.


person scriptfoo    schedule 17.03.2021    source источник
comment
на основе предоставленного вывода вы работаете на локальном хосте, верно? что за операционная система? возможно ли, что у вас есть какой-то мошеннический антивирус, vpn или брандмауэр, который вам нужно обойти?   -  person eis    schedule 18.03.2021
comment
единственный инструмент, который я нашел, который выводил <unreadable>, был отладчик gdb... так что у вас нет никаких инструментов отладки, мешающих вашему программному обеспечению?   -  person eis    schedule 18.03.2021
comment
Приложения прослушивают https://localhost:8443, браузер (Chrome или FIrefox) находится в той же локальной системе. Система — Linux Mint, производная от Ubuntu 18.04. Я никогда не устанавливал здесь ни антивирус, ни впн и даже не перенастраивал iptables, но кто его знает.   -  person scriptfoo    schedule 18.03.2021
comment
@eis Это <Unreadable>, т.е. начинается с заглавной буквы.   -  person scriptfoo    schedule 18.03.2021
comment
Существуют ли какие-либо диагностические инструменты, которые показывают, как взаимодействуют приложения в локальной системе?   -  person scriptfoo    schedule 18.03.2021
comment
@scriptfoo у вас есть возможность запустить это приложение на другом компьютере, кроме того, который вы используете в данный момент?   -  person eis    schedule 18.03.2021
comment
также, если вы нажмете конечную точку /command с аналогичным запросом, но с помощью curl или аналогичного инструмента, что произойдет тогда (при том же вводе)   -  person eis    schedule 18.03.2021
comment
Простейшим инструментом @scriptfoo может быть просто запуск netcat, поэтому выключите свой java-сервер, выполните nc -l portnumber с номером порта, с которым вы использовали свой java-сервер, нажмите запрос и посмотрите, что произойдет.   -  person eis    schedule 18.03.2021
comment
также вы можете добавить к вопросу, как CommandServlet на самом деле получает свое содержимое, поэтому начало обработки ввода метода   -  person eis    schedule 18.03.2021
comment
Я нашел своего рода MITM. Это был отладчик Netbeans, не способный отображать строки, превышающие заданный предел. Большое спасибо за помощь, это был намек на то, что причина, вероятно, не имеет ничего общего с веб-программированием. Забавно, что @eis нашел <unreadable> в другом отладчике. Возможно, некоторая (культурная) зависимость между этими двумя приложениями.   -  person scriptfoo    schedule 18.03.2021
comment
@BalusC Нет, это новый сервлет. Я проверил, получает ли он хорошие данные, и что ж... это так. Я этого не сделал. Да, это была отладочная разработка fetch, потому что мои знания Javascript ограничены.   -  person scriptfoo    schedule 18.03.2021
comment
@scriptfoo здорово! Пожалуйста, добавьте это как ответ и отметьте его как принятый, чтобы этот вопрос отображался как решенный.   -  person eis    schedule 18.03.2021
comment
@scriptfoo, по крайней мере, netbeans/C++ фактически использует отладчик gdb внутри, так что это может быть тот же инструмент, о котором мы говорим, или клон/порт/вдохновленный тем же   -  person eis    schedule 18.03.2021


Ответы (1)


Комментаторы заподозрили, что что-то мешает. Одной из подсказок был отладчик, потому что gdb использует похожее сообщение, только не начинающееся с заглавной буквы. На самом деле сообщение (замаскированное под реальное значение переменной) было создано где-то в цепочке отладки Netbeans/JPDA/JVM.

person scriptfoo    schedule 18.03.2021