Stalker Опубликовано 23 декабря, 2019 Поделиться Опубликовано 23 декабря, 2019 Hi All, Delphi 10.3.3. На текущий момент VCL, дальше будет FMX для мобильных платформ. Имеется Web-Сервис который вызывается через Post с передачей ему параметров в виде x-www-form-urlencoded. в теле запроса. Параметры могут содержать русские буквы, поэтому они должны быть переданы в сервис в UTF8. Вызовом этого сервиса занимается следующий код: var ASource :TStringList; cResponce :String; begin ASource := TStringList.Create(); ASource.Add('nParam1=1'); ASource.Add('cParam2='+UTF8Encode(Edit1.Text)); ASource.Add('cParam3='+UTF8Encode(Edit2.Text)); ASource.Add('cParam4='+UTF8Encode(Edit3.Text)); cResponce := NetHTTPClient1.Post('https://сайт/сервис', ASource).ContentAsString(TEncoding.UTF8); FreeAndNil(ASource); Сам код работает нормально, сервис вызывается, данные возвращаются. НО для передачи параметров в UTF8 приходится использовать функцию UTF8Encode, что приводит в Warning'у от Delphi: Цитата W1057 Implicit string cast from 'RawByteString' to 'string' Вопрос: Как правильно организовать кодирование параметров в UTF8, что бы этого Warning'а не было ? Цитата Ссылка на комментарий
0 Slym Опубликовано 23 декабря, 2019 Поделиться Опубликовано 23 декабря, 2019 а попробовать не кодировать? может оно само! Цитата Ссылка на комментарий
0 Stalker Опубликовано 23 декабря, 2019 Автор Поделиться Опубликовано 23 декабря, 2019 Пробовал конечно. В этом случае на сервер приходит русский текст в кодировке windows-1251 (ANSI). Цитата Ссылка на комментарий
0 Slym Опубликовано 23 декабря, 2019 Поделиться Опубликовано 23 декабря, 2019 (изменено) Post(const AURL: string; const ASource: TStrings; const AResponseContent: TStream = nil; const AEncoding: TEncoding = nil; cResponce := NetHTTPClient1.Post('https://сайт/сервис', ASource,nil, TEncoding.UTF8) .ContentAsString(TEncoding.UTF8); и смотрим заголовок application/x-www-form-urlencoded; charset=??? Изменено 23 декабря, 2019 пользователем Slym Цитата Ссылка на комментарий
0 Stalker Опубликовано 23 декабря, 2019 Автор Поделиться Опубликовано 23 декабря, 2019 Это я тоже пробовал. Или оно для другого или не работает как надо. Кроме того, если Вы пройдете по коду NetHTTPClient1.Post внутрь исходников, то в THTTPClient.Post в коде THTTPClient.CreateFormFromStings есть такая проверка: if AEncoding = nil then LEncoding := TEncoding.UTF8 else LEncoding := AEncoding; То есть по умолчанию оно все равно будет UTF8 . Но как я уже сказал выше это не помогает. Цитата Ссылка на комментарий
0 krapotkin Опубликовано 23 декабря, 2019 Поделиться Опубликовано 23 декабря, 2019 а все-таки, заголовки какие передаются? мало ли что мы предполагаем. я помню, раскапывал код Post, так они там вообще не всегда прикладывались. Выбрал вариант, где они есть в явном виде и с тех пор использую его... Цитата Ссылка на комментарий
0 Stalker Опубликовано 23 декабря, 2019 Автор Поделиться Опубликовано 23 декабря, 2019 Вызывал Post и как NetHTTPClient1.Post('https://сайт/сервис', ASource,nil, TEncoding.UTF8) .ContentAsString(TEncoding.UTF8); и как NetHTTPClient1.Post('https://сайт/сервис', ASource) .ContentAsString(TEncoding.UTF8); В обоих случаях заголовок, который приходит на сервер, одинаковый: Цитата HEADER: Connection=Keep-Alive HEADER: Content-Type=application/x-www-form-urlencoded; charset=utf-8 HEADER: @HttpURI=/сервис HEADER: @HttpMethod=POST HEADER: Authorization=Basic d2dfVzqdUwQ== HEADER: Host=сайт HEADER: @HttpVersion=HTTP/1.1 HEADER: User-Agent=Embarcadero URI Client/1.0 HEADER: @MediaType=application/x-www-form-urlencoded HEADER: Content-Length=109 Цитата Ссылка на комментарий
0 Tumaso Опубликовано 23 декабря, 2019 Поделиться Опубликовано 23 декабря, 2019 (изменено) Пример моего кода, который корректно отправляет/получает данные: function Post(const ASession: TNetHTTPClient; const AUrl: string; const ASource: TStrings; const AIsURLEncode: Boolean): string; var LResult: TStringStream; begin Result := ''; LResult := TStringStream.Create('', TEncoding.UTF8); try ASession.AcceptCharSet := 'utf-8'; if AIsURLEncode then ASession.Post(TNetEncoding.URL.Encode(AUrl, [], []), ASource, LResult) else ASession.Post(AUrl, ASource, LResult); Result := LResult.DataString; finally LResult.DisposeOf; end; end; Изменено 23 декабря, 2019 пользователем Tumaso Цитата Ссылка на комментарий
0 Stalker Опубликовано 23 декабря, 2019 Автор Поделиться Опубликовано 23 декабря, 2019 Попробовал Ваш метод. Сам сервис вызывается, но параметры в него все равно передаются в windows-1251, а не в UTF-8 и соответственно искомые данные не находятся. То есть все равно приходится использовать UTF8Encode. Так что Ваш вариант к сожалению тоже не помог и основной вопрос остается актуальным. Суда по всему данные в Edit.Text в 1251, а перекодировкой параметров из ASource метод TNetHTTPClient.Post не занимается. P.S. Пара вопросов по вашему методу: 1. Почему DisposeOf, а не Free или FreeAndNil ? 2. Чем вариант возвращения данных запроса в LResult (в параметр) лучше, чем возвращаемый самим методом TNetHTTPClient.Post ? Цитата Ссылка на комментарий
0 krapotkin Опубликовано 23 декабря, 2019 Поделиться Опубликовано 23 декабря, 2019 (изменено) что-то не сходится в показаниях я тоже абсолютно корректно посылаю принимаю данные на win и android и все в правильной кодировке безо всяких ухищрений примерно аналогичным кодом что-то важное вы скрываете... vResp := Http.Post(vURL, PostData, FResStream, FHeaders); как версию рассматриваю еще кодирование TNetEncoding.URL.Encode( хотя я например посылаю JSON в POST без кодирования и сервер все принимает нормально Изменено 24 декабря, 2019 пользователем krapotkin Цитата Ссылка на комментарий
0 Stalker Опубликовано 24 декабря, 2019 Автор Поделиться Опубликовано 24 декабря, 2019 16 часов назад, krapotkin сказал: что-то не сходится в показаниях я тоже абсолютно корректно посылаю принимаю данные на win и android и все в правильной кодировке безо всяких ухищрений примерно аналогичным кодом что-то важное вы скрываете... Что например я скрываю ? Есть есть вопросы - задавайте. В атаче я прикрепил демку. Которая использует два варианта Post (мой и Tumaso). Если ставишь галочку "Use UTF8Encode", данные (параметры запроса) в веб-сервис приходят в utf-8, если не ставишь то в windows-1251. Дергал этот же сервис их Postman - там всегда параметры приходят в сервис в utf-8. demo.rar Цитата Ссылка на комментарий
1 Slym Опубликовано 25 декабря, 2019 Поделиться Опубликовано 25 декабря, 2019 HTTPAnalyzer показывает: POST / HTTP/1.1 Connection: Keep-Alive Content-Type: application/x-www-form-urlencoded; charset=utf-8 User-Agent: Embarcadero URI Client/1.0 Host: www.yandex.ru Content-Length: 148 nOwnerOrganizMode=1&cRegNumber=%D1%81-5%2F1&cBegRegDate=22.05.2029&cFIO=%D1%81%D0%B5%D1%80%D0%B3&cDocContent=%D0%B9%D1%86%D1%83qwe%D0%B9%D1%86%D1%83 Обилие %D0 - показывают что уходит UNICODE, а кодирование цифр и английского одним символом указывает что это UTF8... и заголовки этому соответствуют Проблема на клиенте отсутствует... копай сервис Евгений Корепов 1 Цитата Ссылка на комментарий
0 Stalker Опубликовано 26 декабря, 2019 Автор Поделиться Опубликовано 26 декабря, 2019 В 25.12.2019 в 04:58, Slym сказал: Проблема на клиенте отсутствует... копай сервис Большое Вам спасибо за подсказку, направили меня по верному пути. Проблема оказалась действительно в сервисе, а точнее в том, как он видит значения параметров в зависимости от заголовка. Если в HEADER указано Content-Type=application/x-www-form-urlencoded; charset=utf-8 то сервис делает автоматическую конвертацию из utf-8 в 1251 (эта кодировка базы сервиса) А если указано Content-Type=application/x-www-form-urlencoded то автоматическая конвертация не делается и ее должен сделать сам разработчик сервиса. А так как раньше я тестировал свои сервисы только на Postman (а у него по умолчания второй вариант), то я всегда делал эту конвертацию сам. Отсюда и был баг неправильного значения параметра. Цитата Ссылка на комментарий
Вопрос
Stalker
Hi All,
Delphi 10.3.3. На текущий момент VCL, дальше будет FMX для мобильных платформ.
Имеется Web-Сервис который вызывается через Post с передачей ему параметров в виде x-www-form-urlencoded. в теле запроса.
Параметры могут содержать русские буквы, поэтому они должны быть переданы в сервис в UTF8.
Вызовом этого сервиса занимается следующий код:
var ASource :TStringList; cResponce :String; begin ASource := TStringList.Create(); ASource.Add('nParam1=1'); ASource.Add('cParam2='+UTF8Encode(Edit1.Text)); ASource.Add('cParam3='+UTF8Encode(Edit2.Text)); ASource.Add('cParam4='+UTF8Encode(Edit3.Text)); cResponce := NetHTTPClient1.Post('https://сайт/сервис', ASource).ContentAsString(TEncoding.UTF8); FreeAndNil(ASource);
Сам код работает нормально, сервис вызывается, данные возвращаются.
НО для передачи параметров в UTF8 приходится использовать функцию UTF8Encode, что приводит в Warning'у от Delphi:
Вопрос: Как правильно организовать кодирование параметров в UTF8, что бы этого Warning'а не было ?
Ссылка на комментарий
12 ответов на этот вопрос
Рекомендуемые сообщения
Присоединяйтесь к обсуждению
Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.