Попытка повторить успешный запрос POST с помощью JSoup - данные, отправленные на сервер, не декодируются

Заголовок HTTP-запроса:

Host: www.mysite.com
Content-Type: application/x-www-form-urlencoded
Cookie: bbuserid=XXX; bbpassword=YYY; bbsessionhash=ZZZ
Content-Length: 252

Тело HTTP-запроса:

message=%E4%F6%F5%FC%E4%F6%F5%FC%E4%F6%F5%FC%E4%F6%F5%FC&securitytoken=XXX&do=postreply&t=483553

Работает нормально! Данные, отправленные на сервер, декодируются на другом конце, и пользователь видит исходное сообщение äöõüäöõüäöõüäöõü.

Теперь давайте попробуем реализовать этот точный пример с помощью JSoup:

//request body 
Map<String, String> datamap = new HashMap<String, String>();
datamap.put(Session.SESSION_SECURITYTOKEN,"XXX");
datamap.put("message", URLEncoder.encode(finalText, "ISO-8859-1"));
datamap.put("do", "postreply");
datamap.put("t", "483553");

//make a post
Jsoup.connect(url)
.header("Content-Type","application/x-www-form-urlencoded")
.timeout(10000)
.cookie(Session.COOKIE_HASH_KEY,session.bbsessionhash)
.cookie(Session.COOKIE_PASSWORD_KEY,session.bbpassword)
.cookie(Session.COOKIE_USERID_KEY,session.bbuserid)
.data(datamap).post();

Мое сообщение публикуется, НО оно не декодируется сервером. Итак, когда пользователь просматривает сообщение, он/она видит: %E4%F6%F5%FC%E4%F6%F5%FC%E4%F6%F5%FC%E4%F6%F5%FC

Примечание. Я делаю почтовый запрос с Android и отправляю данные в программное обеспечение форума vBulletin (воспроизведение в ветке).

Проблема: когда я отправляю сообщение с помощью JSoup, сервер видит его как обычный текст, а не закодированный текст. Как заставить сервер понять, что параметр сообщения содержит закодированный текст, а не обычный текст?


person Indrek Kõue    schedule 08.11.2011    source источник
comment
Я не знаком с Jsoup, но думаю, что он кодирует свои параметры в методе data. Таким образом, использование URLEncoder.encode для значения кодирует данные дважды.   -  person McDowell    schedule 09.11.2011
comment
Удаление URLEncoder.encode добавляет простой текст к параметру сообщения, и я теряю определенные символы, которые необходимо кодировать. Рабочий запрос POST каким-то образом сообщает серверу, что сообщение закодировано, и вы (сервер) должны его декодировать. Но когда я пытаюсь воспроизвести его, сервер воспринимает сообщение как обычный текст. Любая идея, как я могу заставить сервер понять, что параметр сообщения содержит закодированный текст, а не обычный текст?   -  person Indrek Kõue    schedule 09.11.2011


Ответы (1)


Jsoup по умолчанию использует UTF-8 для URL-кодирования строки запроса. В текущей версии API вы не можете изменить его без перестроения исходного кода (это константа org.jsoup.helper.DataUtil#defaultCharset, которая использовалась в классе org.jsoup.helper.HttpConnection). Лучшее, что вы можете сделать, это опубликовать отчет о проблеме с просьбой заранее установить кодировку.

До тех пор вы можете использовать HttpClient или URLConnection, что позволяет более точно контролировать отправку HTTP-запросов. Наконец, вы можете передать его ответ как метод от InputStream до Jsoup#parse().


Обновление: если целевой веб-сайт поддерживает это, вы можете попробовать явно указать кодировку, используемую клиентом, в заголовке запроса Content-Type:

.header("Content-Type","application/x-www-form-urlencoded;charset=UTF-8")

Обратите внимание, что вы не должны использовать URLEncoder#encode() самостоятельно; пусть Jsoup делает свою работу.

person BalusC    schedule 09.11.2011
comment
Правильно ли я понимаю, что JSoup автоматически кодирует каждое тело HTTP POST в UTF-8, и его невозможно изменить (без редактирования исходного кода JSoup и перекомпиляции jar)? - person Indrek Kõue; 10.11.2011
comment
Это правильно. Jsoup, однако, является относительно новым API и нуждается в более тонкой настройке, чтобы лучше соответствовать разумным сценариям использования в реальном мире. Новые вопросы и пожелания всегда приветствуются. См. также последний абзац его Connection javadoc: jsoup.org/apidocs/org/jsoup/ Connection.html Что касается выбора UTF-8; это, скорее всего, потому, что Jsoup разработан как парсер HTML5, а HTML5 требует UTF-8 в качестве набора символов по умолчанию. Ваш целевой сайт просто устарел с этой точки зрения :) - person BalusC; 10.11.2011
comment
См. обновление ответа; это будет работать, если целевой веб-сайт поддерживает это, но не удивляйтесь, если это не будет соблюдаться целевым веб-сайтом (что на самом деле будет собственной ошибкой целевого веб-сайта). - person BalusC; 10.11.2011