При разработке систем интеграции между мобильными приложениями на Android и HTTP-сервисами 1С программисты часто сталкиваются с ситуацией, когда запросы, прекрасно работающие в браузере или на новых версиях Android, «теряют» часть данных на старых устройствах (Android 6 и ниже). В этой статье мы подробно разберем, почему пропадают параметры запроса, как влияет кодировка URL на стабильность связи и как правильно перевести обмен данными на метод POST для обеспечения максимальной надежности.
Рассмотрим стандартную ситуацию: мобильное приложение отправляет GET-запрос к базе 1С для авторизации пользователя. В строке запроса передаются логин и пароль. На современных устройствах всё работает корректно, однако на версиях Android 6 и ниже второй параметр (например, &pass=...) может попросту не доходить до 1С. Проанализируем типичный код формирования запроса на стороне Android:
URL url = new URL(String.format("http://server/base/hs/auth/v1?login=%s&pass=%s", login, pass));
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
Основная причина проблемы кроется в некорректном экранировании спецсимволов в URL. Символы пробела, точки, кириллица или знаки препинания в логине или пароле разрывают структуру URI. В старых версиях Android механизмы автоматического кодирования строк работают менее гибко, чем в современных браузерах. Например, если в логине присутствует пробел (например, "Иванов И.И."), и он не был преобразован в %20, сервер (IIS или Apache) может воспринять это как конец заголовка запроса или некорректный путь, обрезая всё, что идет после пробела.
Выясним еще одну важную деталь: 1С воспринимает объект Запрос как уже разобранный URI. Если структура строки нарушена на этапе передачи, коллекция Запрос.ПараметрыЗапроса будет содержать только те элементы, которые удалось распознать до первого «критичного» символа.
Первым шагом в исправлении ситуации должно стать принудительное кодирование всех строковых параметров, передаваемых в GET-запросе. В 1С для этих целей можно использовать MSScriptControl (если работа идет на Windows-сервере) или встроенные средства платформы для работы со строками. Однако правильнее всего обрабатывать это на стороне отправителя (Android).
Вместо прямой склейки строк в Android следует использовать URLEncoder.encode(string, "UTF-8"). Это преобразует "Иванов И.И." в " %D0%98%D0%B2%D0%B0%D0%BD%D0%BE%D0%B2%20%D0%98.%D0%98.". Рассмотрим, как это влияет на стабильность:
%20 или +.&, ?, #) внутри параметров не конфликтуют с разделителями самого URL.Если же параметры содержат сложные данные (например, длинные описания задач), GET-запрос может столкнуться с ограничением по длине строки (обычно около 2048 символов), что также приведет к обрезке данных.
Если изменение логики приложения затруднено, можно применить промежуточное решение — кодирование всей строки параметров или отдельных значений в Base64. Это гарантирует, что в URL будут передаваться только «безопасные» символы латинского алфавита и цифры.
Проанализируем пример на стороне 1С для расшифровки таких данных:
Функция ПолучитьПараметрыИзBase64(ЗначениеBase64)
ДвоичныеДанные = ИзBase64Строки(ЗначениеBase64);
СтрокаПараметров = ПолучитьСтрокуИзДвоичныхДанных(ДвоичныеДанные, КодировкаТекста.UTF8);
Возврат СтрокаПараметров;
КонецФункции
Важное ограничение: Кодирование Base64 увеличивает объем передаваемых данных примерно на 33%. На старых устройствах Android при передаче больших текстов это может привести к превышению лимита длины URL еще быстрее, чем при обычном тексте.
Самым надежным и профессиональным способом решения проблемы является использование метода POST вместо GET. При использовании POST данные передаются не в заголовке (URL), а в теле запроса. Это снимает ограничения на длину и избавляет от проблем с интерпретацией спецсимволов веб-сервером.
Разберем реализацию POST-запроса на Android:
static String sendPostData(String dataToPost) {
try {
URL url = new URL("http://your-1c-server/hs/myservice/auth");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
OutputStream os = conn.getOutputStream();
os.write(dataToPost.getBytes("UTF-8"));
os.flush();
os.close();
// Чтение ответа...
} catch (Exception e) {
return "Error: " + e.getMessage();
}
}
Теперь проанализируем, как правильно принять эти данные в 1С. Обратите внимание: при использовании метода POST параметры больше не будут доступны в коллекции Запрос.ПараметрыЗапроса. Их нужно извлекать из тела запроса.
Функция ОсновнойPOST(Запрос)
// Получаем данные из тела запроса
ДанныеСтрокой = Запрос.ПолучитьТелоКакСтроку("UTF-8");
// Если мы передавали JSON, то десериализуем его
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(ДанныеСтрокой);
СтруктураДанных = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
Логин = СтруктураДанных.login;
Пароль = СтруктураДанных.pass;
// Выполняем логику...
Результат = Авторизация(Логин, Пароль);
Ответ = Новый HTTPСервисОтвет(200);
Ответ.УстановитьТелоИзСтроки(Результат);
Возврат Ответ;
КонецФункции
Рассмотрим ситуации, когда даже после перехода на POST данные в 1С «не видны»:
application/json, а отправляется строка вида login=admin&pass=123, 1С может не считать тело корректно или возникнет ошибка парсинга. Убедитесь, что формат отправляемых данных соответствует заголовку.UTF-8 как при отправке из мобильного приложения, так и при чтении в методе Запрос.ПолучитьТелоКакСтроку("UTF-8").Запрос.ПараметрыЗапроса в 1С работает только для данных, идущих после знака ? в URL. Тело POST-запроса — это отдельный поток данных.Чтобы точно понять, что именно приходит от мобильного устройства, воспользуйтесь записью «сырых» данных в журнал регистрации. Это поможет выяснить, на каком этапе происходит искажение — в Android-коде или уже внутри 1С.
Добавьте следующий код в начало вашей функции в 1С:
ЗаписьЖурналаРегистрации("HTTP.Debug",
УровеньЖурналаРегистрации.Информация, , ,
"Тело: " + Запрос.ПолучитьТелоКакСтроку() +
"; Параметры: " + Запрос.ПараметрыURL.Получить("ИмяМетода"));
Посмотрим на результат в Журнале регистрации: если в теле пусто, значит проблема на стороне Android-приложения (неправильно открыт OutputStream). Если данные есть, но они «битые», проверьте кодировку и использование URLEncoder.
Использование связки POST + JSON + UTF-8 является «золотым стандартом» мобильной разработки и гарантирует, что ваше приложение будет стабильно работать на любой версии Android, независимо от сложности передаваемых данных и наличия спецсимволов в логинах или задачах.