Плюсики заменяются пробелами в http запросах? Секрет исходного кода

исходный код

Это первая часть того, почему технологии20оригинальная статья

Иногда вы видите исходный код, а это значит, что вы его очень глубоко прочитали. Иногда вы видите исходный код, но вы все еще на поверхности.

За исходным кодом скрываются секреты.Другие только говорят вам, что он написан по историческим причинам, но эта статья расскажет вам, каковы исторические причины.

在这里插入图片描述
На этой неделе у меня не было времени писать технические статьи, чтобы не отставать от недели, я просто подумал о переносе оригинальной статьи, опубликованной на других платформах. Оказалось, что статья, которую я написал тогда, была далеко неПравда еще за тысячу миль.

Когда я искал этот вопрос, моя статья была первым результатом.

在这里插入图片描述

Ссылка на оригинал "Плюсик в параметре http-запроса заменяется пробелом и параметр запроса записывается URLDeCode" выглядит следующим образом:woohoo.brief.com/afraid/1ah30not585от…

Поэтому, чтобы не продолжать вводить читателей в заблуждение, даже если выходные «лопнут печень», эту статью надо выводить и обязательно размещать.

Это мой самосовершенствование как программиста.

плюс знак пробела

Причиной написания этой статьи раньше было то, что я столкнулся с двумя интересными проблемами, а именно:

在这里插入图片描述

Во-первых, мы воспроизведем сцену, и мы не будем говорить о процессе сборки проекта, разве не легко собрать простой веб-проект с idea + springboot?

在这里插入图片描述

Как показывает приведенное выше явление: мои входные параметрыjay+love, но полученный фонjay love, знак плюс становится пробелом. Зачем?

Никаких секретов под исходным кодом

Версия исходного кода Tomcat, проанализированная в этой статье: 9.0.29.

在这里插入图片描述

Можно найти через Debugдва ключевых моментакод:

Первое место:org.apache.tomcat.util.http.Parameters#processParameters(byte[], int, int, java.nio.charset.Charset) строка 290 на изображении ниже

在这里插入图片描述
в этом местеИз-за «+» установите для параметра decodeValue значение true, указывая на то, что значение в запросе необходимо декодировать.

Конкретное расположение исходного кода декодирования выглядит следующим образом, это второй ключевой код:org.apache.tomcat.util.buf.UDecoder#convert(org.apache.tomcat.util.buf.ByteChunk, boolean)

在这里插入图片描述
在这里插入图片描述

Видно, что в исходном коде есть фрагмент кода, который заменяет «+» пробелами, и эта специальная обработка сделана преднамеренно.

Весь метод интерпретируется следующим образом:

在这里插入图片描述

Итак, моя записьjay+love, но полученный фонjay love, знак плюс становится пробелом. Зачем?

Причина очень проста: в исходном коде есть фрагмент кода, который намеренно заменяет «+» пробелом.

Зачем это делать?

В предыдущей статье я писал:

在这里插入图片描述

По историческим причинам, какова историческая причина?

Я искал в Интернете и не мог найти конкретной исторической причины, все статьи, которые я видел по этой проблеме, либо давали только решения, либо указанная выше историческая причина была просто мимолетной и неоднозначной.

Вот, я скажу вам, почему.

Спустя долгое время я нашел много зацепок.После разбора решилНачнем с «ОШИБКИ» JDK.

Соответствующая ссылка:не говорите.sun.com/view_but.do…

在这里插入图片描述

Как видно из времени подачи,На эту проблему указывали еще в 2001 году, 18 лет назад., и сообщил об ошибке в JDK. Его описание выглядит следующим образом:

在这里插入图片描述

Во-первых, давайте возьмем его тестовый код и запустим его:

在这里插入图片描述

Почему он сказал, что пробел после кодирования должен быть %20?

Потому что он упомянул об этом в ошибкеRFC2396стандарт. (RFC не будет объяснять это, вам нужно только знать, что это авторитетный стандарт, сертифицированный в отрасли):адрес:Уууу, я ETF.org/RFC/RFC2396…

在这里插入图片描述
В разделе 2.4.1 RFC2396 четко указано, что «%20» — это управляющая кодировка символа пробела US-ASCII.

Чтобы запросить стандартный код ASCII, вы также можете обнаружить, что это действительно так:

在这里插入图片描述

Попрактикуйтесь с кодом, чтобы доказать приведенный выше вывод:

在这里插入图片描述

Глядя на исходный код java.net.URLEncoder#encode(java.lang.String, java.lang.String) также можно интуитивно увидеть,В исходном коде произведена специальная обработка:

在这里插入图片描述

Посмотрите исходный код java.net.URLDecoder#decode(java.lang.String, java.lang.String):

在这里插入图片描述

здесь и раньшеповторил, это обрабатывается точно так же. Итак, почему это обрабатывается таким образом, два места принадлежатгомологичныйКакие!

И почему парень, который упомянул ОШИБКУ, думает, что это ОШИБКА?

Хотя после тестирования '+' и '%20' можно после декодирования преобразовать в пробелы, но он считает, что согласно RFC2396 может быть только '%20', как его можно превратить в '+'? Поэтому он подумал, что это ошибка.

тогда посмотримКак официальный представитель JDK ответил на этот вопрос?

在这里插入图片描述

Официальный ответ:Это не ошибка, мой друг! Этот класс следует положениям спецификации HTML: как кодировать URL-адреса в HTML-формах. Он не предназначен для других целей. И причина этого в том, что таким образом предусмотрено включение HTML 4.01, раздел 17.13.4 и RFC 1866 (который был заменен Рекомендацией W3C по HTML).

Для первого абзаца я понимаю официальное значение: этот класс используется для кодирования URL-адреса, а не для других целей. Поскольку вы вызвали encode, вам нужно декодировать и декодировать.Мне просто нужно убедиться, что данные после декодирования такие же, как данные до кодирования. Если вы хотите использовать его для других целей, я не могу это контролировать.

И зачем это делать? Это потому, что правила такие, похожие на национальные стандарты и требования, выдвигаемые менеджерами по продукту. Здесь чиновник выдвинул два стандарта,Один — HTML 4.01, другой — RFC1866.(Это было заменено другими стандартами, так что давайте просто посмотрим на HTML 4.01).HTML4.01 был выпущен 24 декабря 1999 г. и содержит небольшие улучшения на основе HTML4.0, рекомендован W3C. Стандарт можно найти на w3c по следующему адресуЯ 3.org/TR/HTML401/…

Место, обведенное на следующем рисунке, очень важно, вы можете щелкнуть, чтобы открыть его для увеличения:

在这里插入图片描述

оказатьсяHTML 4.01 Раздел 17.13.4, в котором четко указано: когда тип содержимого имеет значение application/x-www-form-urlencoded, имена и значения экранируются, а пробелы заменяются знаком «+».

Раздел 17.13.4 HTML 4.01 выглядит следующим образом:Control names and values are escaped. Space characters are replaced by `+'

Хотя официальным примером является HTML 4.01, я перевел исторические документы и обнаружил, что на самом деле это было предусмотрено в более ранней спецификации HTML 3.2.Спецификация HTML 3.2 стала рекомендацией W3C в 1996 году., соответствующее содержание выглядит следующим образом:

адрес ссылки:Я 3.org/TR/2018/SPS…

在这里插入图片描述

А application/x-www-form-urlencoded — это тип содержимого браузера по умолчанию.

упоминается в ошибкеСтандарт RFC2396 был предложен в августе 1998 г.:

在这里插入图片描述

иСпецификация HTML 3.2 стала рекомендацией W3C в 1996 году.

Я так думаюЭто историческая причина!

Опять же, это четко указано в спецификации HTML 4.01: когда тип содержимого имеет значение application/x-www-form-urlencoded, имена и значения экранируются, а пробелы заменяются на «+».

Нет причин, это правило! В процессе расследования я обнаружил, что у других языков программирования также есть эта проблема, потому что все они следуют одним и тем же стандартам и имеют одни и те же «исторические причины».

Вернуться к этому месту ранее:

在这里插入图片描述

Зачем преобразовывать «+» в пробелы при декодировании здесь? По «историческим причинам», если пробелы появляются в URL-адресах, их необходимо заменить на «+», поэтому «+» преобразуется обратно в пробелы при декодировании. Сначала идет операция кодирования, поэтому будет операция декодирования.

Во многих статьях говорится, что это причина «+», и даже в некоторых статьях говорится, что кодировку «+» следует изменить на %20. Но на самом деле, приведенный выше анализ, проблема в пространстве, а не в «+».

Тогда почему мы часто пишем знак "+" при отправке формы?Почему нет проблем?

**Поскольку при отправке Html-формы каждое поле формы будет закодировано в виде URL-адреса перед отправкой. **Можно доказать следующий небольшой пример:

在这里插入图片描述

решение

В Интернете есть много решений, позвольте мне перечислить их здесь:

Вариант 1. Измените клиент и замените все «+» в параметрах на «+» в клиенте на «%2B» следующим образом:

Вариант 2: Измените серверную часть и замените пробел на «+», этот метод применим только в случае, когда в параметре нет пробела в «+». следующее:

在这里插入图片描述

Вариант 3: Изменить серверную часть, изменить метод получения параметров с ‍reuqest.‍getParameter на ‍request.getQueryString(), а затем проанализировать полученную строку.

在这里插入图片描述

Последнее слово

Как я уже сказал в начале своей статьи, даже если бы я не спал всю ночь, мне пришлось бы выводить эту статью, потому что моя первая статья была не только поверхностной, но и имела некоторые проблемы, которые мне нужно было исправлять.

Это вдруг напомнило мне о разговоре, который у меня был раньше с другом, он спросил меня: как программист, ты всегда на связи, и как только возникнут проблемы с системой, ты сразу же отреагируешь. Вы не чувствуете усталости?

Я ответил: «Серьезно, я не чувствую усталости, когда есть проблема с системой, и мне нужно решить эту проблему. Поскольку эта система находится под моей ответственностью, код пишется мной построчно. Если есть проблема, я должен доказать, что в моей системе нет проблем, неправильный ли это способ открытия. Но если бы мой код действительно вызывал проблему, я бы чувствовал себя виноватым, и я должен был бы немедленно реагировать и брать на себя ответственность за это.

Это мой самосовершенствование как программиста.

Стиль этой статьи немного похож на «Я действительно не знаю, что интервьюер хочет ответить на этот вопрос интервью». Полный текст описывает очень маленькие точки знаний или даже холодные знания. Одним предложением можно сказать почему на поверхности и извлечь очко знаний.

Но я думаю, что то, что я извлек, является сморщенным знанием, оно недостаточно богато, и в нем нет процесса исследования.

И то, что я показываю, — это мой процесс поиска ответа на этот вопрос. Несколько протоколов соединены последовательно через «ОШИБКУ» JDK, и это протокол, которому следует весь мир, что является чрезвычайно авторитетным.

Если вам не хватает таланта и обучения, неизбежно будут ошибки.Если вы обнаружите какие-либо ошибки, пожалуйста, оставьте сообщение и укажите на это мне, и я его исправлю.

Спасибо за прочтение и за внимание.

выше.