Jetty Utf8Appendable $ NotUtf8Exception по запросу ISO-8859 с пружиной - PullRequest
3 голосов
/ 04 февраля 2012

Удаленная служба вызывает наш Jetty Server с запросом, закодированным в ISO-8859-15. Этот специальный запрос отображается на Spring Controller. Jetty не может правильно закодировать запрос и показывает следующее исключение:

exception=org.eclipse.jetty.util.Utf8Appendable$NotUtf8Exception: Not valid UTF8! byte F6 in state 3}
org.eclipse.jetty.util.Utf8Appendable$NotUtf8Exception: Not valid UTF8! byte F6 in state 3
    at org.eclipse.jetty.util.Utf8Appendable.appendByte(Utf8Appendable.java:168) ~[na:na]
    at org.eclipse.jetty.util.Utf8Appendable.append(Utf8Appendable.java:93) ~[na:na]
    at org.eclipse.jetty.util.UrlEncoded.decodeUtf8To(UrlEncoded.java:506) ~[na:na]
    at org.eclipse.jetty.util.UrlEncoded.decodeTo(UrlEncoded.java:554) ~[na:na]
    at org.eclipse.jetty.server.Request.extractParameters(Request.java:285) ~[na:na]
    at org.eclipse.jetty.server.Request.getParameter(Request.java:695) ~[na:na]
    ....

Решение

Весной можно принудительно закодировать запрос через CharacterEncodingFilter, даже если все приложение говорит на UTF-8. Исключение должно исчезнуть.

<filter>
    <filter-name>encoding-filter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>ISO-8859-15</param-value>
    </init-param>
    <init-param>
        <param-name>forceEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>encoding-filter</filter-name>
    <url-pattern>/app/specialRequest.do</url-pattern>
</filter-mapping>

Если это не работает для вас

  • узнать кодировку удаленной системы
  • запустить Wireshark для анализа входящего пакета через фильтр ip.src == xxx.xxx.xxx.xxx
  • поиск в теле запроса специальных символов (пересчитать шестнадцатеричное значение в двоичное и попробовать несколько часто используемых кодировок, чтобы найти именно того, кто соответствует исключению)
  • установить кодировку через start.ini Jetty, т.е. со следующими параметрами

    Dorg.eclipse.jetty.util.URI.charset = ISO-8859-15

    Dorg.eclipse.jetty.util.UrlEncoding.charset = ISO-8859-15

В противном случае, напишите мне, если у вас есть еще вопросы.

1 Ответ

4 голосов
/ 05 февраля 2012

Похоже, что клиент отправляет текст, который должен быть закодирован как UTF8, но не кодирует его.

Чтобы правильно диагностировать эту проблему, вам нужно понять UTF8 (что вы могли бы сделать, Я не знаю)

В UTF8 любой символ с кодировкой 127 (0x7F) или меньше - т.е. используется только самый младший 7 бит - включен в поток как есть (без специальной кодировки).Но все, что больше 127 (т. Е. Установлен по крайней мере один бит выше, чем 7-й), специально закодировано.

0xF6 больше 0x7F, поэтому, если клиент хочет отправить этот символ, он должензакодировал это.

0xF6 в двоичном виде - 11110110, который в UTF8 должен быть 11000011 10110110 (C3 B6)

Итак, если клиент хочет отправить символ ISO8859-1 0xF6, тогда он должен посылать последовательность байтов UTF8 0xC3 0xB6.

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

(«состояние 3», это связано с внутренними таблицами Jetty для выполнения декодирования UTF8, на самом деле это не очень полезно для диагностики этой проблемы. Это пригодится только в случае необходимости).если вы найдете клиента, и похоже, что клиент поступает правильно, и вы подозреваете, что декодирование Jetty UTF8 неверно)

...