Indy HTTPServer и UTF8 и CP1251 проблема конвертации

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Indy HTTPServer и UTF8 и CP1251 проблема конвертации

Сообщение jsa » 09.03.2023 15:09:34

Здравствуйте.
Написал простой REST сервер который работает через Indy компоненты. И выдает данные из MS SQL сервера

Проблема с кодировкой.
Ответ Response выдается в кодировке CP1251 чего бы я не делал

Код: Выделить всё
var rResponce: widestring;   
thr_Query: TSQLQuery;  <<<---- помещается запрос и выполняется Open, возвращается 1 запись с кодом и строкой XML

....

AResponseInfo.ContentType:='text/xml;charset='+Response_charset+';' 
AResponseInfo.ResponseNo := thr_Query.Fields.Fields[1].AsInteger; 

rResponce:=thr_Query.Fields.Fields[0].AsWideString;
AResponseInfo.ContentLength := length( rResponce );   

AResponseInfo.ContentText := rResponce; <<<---- Заменяемая строка

MemoLog.Lines.Add( rResponce );
Append(FLOG); Writeln(FLOG, rResponce); Close(FLOG); 

...


В целом REST работает нормально, выдает ответы на запросы в JSON или XML , но строки на кириллице выдаются не правильно.
Например в тестовом запросе выдается XML где есть слова "врач-терапевт"
Дальше я перебираю варианты функций перекодировки, и смотрю результаты
1. в ответе запроса в ARC клиента
2. в Memo поле в REST сервере (да, пока это не в виде службы сделано)
3. файле лога

Код: Выделить всё
----------------

...
AResponseInfo.ContentText := rResponce;
...

ARC-client
врач-терапевт

Memo и файл txt
врач-терапевт

-----------------

...
AResponseInfo.ContentText := UTF8ToWinCP(rResponce); 
...

ARC-client
врач-терапевт

Memo и файл txt
врач-терапевт

-----------------

...
AResponseInfo.ContentText := WinCPtoUTF8(rResponce); 
...

ARC-client          
врач-терапевт   

Memo и файл txt
врач-терапевт

-----------------

...
rResponce := WinCPtoUTF8(rResponce);
AResponseInfo.ContentText := rResponce;
...

ARC-client
врач-терапевт

Memo и файл txt
врач-терапевт

-----------------

...
rResponce := UTF8toWinCP(rResponce);
AResponseInfo.ContentText := rResponce;

ARC-client
пїЅпїЅпїЅпїЅ-пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ

Memo и файл txt
????-????????  а в файле ����-��������

-----------------
var rResponce: string;  // т.е. поменял widestring на string
...
rResponce := UTF8toWinCP(rResponce);
AResponseInfo.ContentText := rResponce;

ARC-client
врач-терапевт

Memo и файл txt
????-????????  а в файле ����-��������

-----------------


А под конец обнаружил, что в тех случаях когда в ARC-client строка отображается нормально (врач-терапевт)
, то это скорее делает с ама программа ARC , и так отображается только при выполнении запроса.
Если же закрыть вкладку запроса и открыть ее из истории то там результат уже отображается (????-????????)

Я уже не знаю что с этим делать и как побороть?
Как сделать нормальную выдачу ответа в UTF8 как положено?
jsa
постоялец
 
Сообщения: 261
Зарегистрирован: 28.11.2017 13:46:04

Re: Indy HTTPServer и UTF8 и CP1251 проблема конвертации

Сообщение wwswowsogon » 09.03.2023 19:31:38

Можете здесь посмотреть: viewtopic.php?f=5&t=43051, обсуждалось недавно нечто подобное, сам долго мучился, потом решил вопрос вот так:

Код: Выделить всё

emmsg.Body.Text := UTF8ToWinCP(emtext);

wwswowsogon
постоялец
 
Сообщения: 152
Зарегистрирован: 23.12.2008 20:41:37

Re: Indy HTTPServer и UTF8 и CP1251 проблема конвертации

Сообщение jsa » 10.03.2023 06:30:05

wwswowsogon писал(а):Можете здесь посмотреть: http://freepascal.ru/forum/viewtopic.php?f=5&t=43051, обсуждалось недавно нечто подобное, сам долго мучился, потом решил вопрос вот так:

Код: Выделить всё
emmsg.Body.Text := UTF8ToWinCP(emtext);



Спасибо за ответ. Этот вариант UTF8ToWinCP тоже перечислен в примерах которые я привел.
Даже 2 раза с переменной типа widestring и переменной типа string
Визуально этот вариант вроде бы работает но ОЧЕНЬ странно (я написал в конце своего первого сообщения), и получатели ответа сообщают, что на самом деле кодировка cp1251 остается

P.S. кстати ту тему тоже я открывал :)
jsa
постоялец
 
Сообщения: 261
Зарегистрирован: 28.11.2017 13:46:04

Re: Indy HTTPServer и UTF8 и CP1251 проблема конвертации

Сообщение delphius » 10.03.2023 09:02:54

jsa писал(а):Как сделать нормальную выдачу ответа в UTF8 как положено?

Возможное решение
delphius
постоялец
 
Сообщения: 122
Зарегистрирован: 18.03.2020 13:40:11

Re: Indy HTTPServer и UTF8 и CP1251 проблема конвертации

Сообщение jsa » 10.03.2023 09:35:52

delphius писал(а):
jsa писал(а):Как сделать нормальную выдачу ответа в UTF8 как положено?

Возможное решение

Спасибо большое.

Код: Выделить всё
var rResponce: widestring;
...
rResponse:=thr_Query.Fields.Fields[0].AsString;
...
AResponseInfo.ContentText := rResponse;
AContext.Connection.IOHandler.DefAnsiEncoding := IndyUTF8Encoding;   

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

Добавлено спустя 1 час 44 минуты 54 секунды:
В общем такой способ тоже не работает.
сделал простой метод/функцию /test_encode

В ARC выдается результат
[{"LAT":"This is a test message to check the encoding","RUS":"Это тестовое сообщение для проверки кодировки","len":120}]

А в любом браузере
[{"LAT":"This is a test message to check the encoding","RUS":"Это тестовое сообщение для пров
т.е. оно кракозябрами да еще и оборвано из-за неверного подсчета длины контента
бедааа

Добавлено спустя 44 минуты 11 секунд:
проверяю тут https://involta.ru/tools/decoder/
в разделе "Определить исходную кодировку"
Браузер действительно получает cp1251

P.S. Заменил AResponseInfo.ContentLength := length( rResponse );
на AResponseInfo.ContentLength := -1; пусть индеец сам считает длину, насчитал 160 вместо 120
теперь в браузере вижу
[{"len":120,"LAT":"This is a test message to check the encoding","RUS":"Это тестовое сообщение для проверки кодировки"}]

Добавлено спустя 1 час 55 минут 27 секунд:
----

Тааак.
Вот тут почитал что народ пишет.

По пробовал через поток, получилась ерунда, к тому же не получилось никак вычислить правильно длину сообщения для передачи в поток влепил просто 150, но это не годится.

Код: Выделить всё
           AResponseInfo.ContentStream := TMemoryStream.Create;
           try
              AResponseInfo.ContentStream.Write(Pointer(rResponse)^, 150);
              AResponseInfo.ContentStream.Position := 0;
              AResponseInfo.WriteContent;
           finally
           AResponseInfo.ContentStream := nil;
           end; 

Эта схема работает если rResponse : string;

----

потом проверил что таки пишу в заголовки, и там был json вместо application/json , поставил второе и в браузерах кодировка стала нормально отображаться.
Это у меня работает совместно с
Код: Выделить всё
AResponseInfo.ContentText := rResponse;
AContext.Connection.IOHandler.DefAnsiEncoding := IndyUTF8Encoding; 

о чем я написал выше.


Теперь надо забороть выдачу и в формате xml , там помоему сервис который шлет запрос не принимает заголовок application/xml пришлось поставить text/xml , сейчас еще потыкаю тот сервис.
jsa
постоялец
 
Сообщения: 261
Зарегистрирован: 28.11.2017 13:46:04


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: S_Gur и гости: 30

Рейтинг@Mail.ru