Проблема
При отправке запросов, при помощи компонента idHTTP возникает проблема, если в строке GET запроса или параметрах POST запроса есть русские символы. Понятное дело, это связано с кодировкой! Выглядит это так (в HTTPAnalyzer)
Естественно, сервера не в курсах, что за вопросы им присылают)))
Я немного поискал решение в сети. Есть официальное решение на официальном форуме Embarcadero, но оно у меня не сработало. Делал вот так…
1 2 3 4 |
{// doesn't work, RUSSIAN_CHARSET symbols still incorrect IdHTTP.IOHandler.DefStringEncoding :=IndyTextEncoding_UTF8; //IndyTextEncoding_UTF8;// << does not help here... IdHTTP.Request.CharSet:='UTF-8'; } |
Что делать, как быть? Менять библиотеку, когда 75% проекта на ней сделано ? Выход нашел следующий.
Решение
Способ №1 через NetEncoding
1 |
uses System.NetEncoding |
Кодируем на клиенте
1 |
TNetEncoding.URL.Encode('Русское слово, параметр POST Запроса или URI GET запроса'); |
На сервере раскодируем
1 |
TNetEncoding.URL.Decode(SomeData); |
Я уже писал об этом в другом посте, но здесь хотел бы привести пример для GET запроса.
Вот простой пример из проекта… Пример GET запроса.
1 2 3 4 5 6 7 8 |
... // Encoding FTempDirForChunksServerChanged:=TNetEncoding.URL.Encode(FTempDirForChunksServerChanged); FileToDownload:= Protocol+'://'+Host+':'+Port+'/'+FTempDirForChunksServerChanged+'UploadlogServer.txt' IdHTTP.IOHandler.DefStringEncoding :=IndyTextEncoding_UTF8; // Nevermind if it is... IdHTTP.Get(FileToDownload,ms); // <<<Sending Encoded URI !!! ... |
На idHTTPServer в CommandGet можно использовать так…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
... //Preparing file for download if it is on the Server begin URIDecoded:=TNetEncoding.URL.Decode(ARequestInfo.URI); // << DECODING if FHTTPServerCommandGet.IsFileOnServerByURI(URIDecoded,filepath,IsWebPage,WebPageContent) then begin AResponseInfo.ResponseNo := 200; if IsWebPage then AResponseInfo.ContentText:=WebPageContent else AResponseInfo.ServeFile(AContext, filepath); end else AresponseInfo.ResponseNo := 404; end; ... |
В результате такого преобразования все работает великолепно !!!
Способ №2 через Base64
Отправка
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
procedure TMain.bTestClick(Sender: TObject); var idHTTP: TIdHTTP; s: TStringStream; data: TStringList; begin idHTTP := TIdHTTP.Create(nil); s := TStringStream.Create; data := TStringList.Create; try Data.Add('phone=79221361449'); Data.Add('message=' + TNetEncoding.URL.Base64.Encode('Привет')); // <<< IdHTTP.Post('http://localhost:50000/sendSms', data, s); mAnswer.Lines.Add(s.DataString); finally idHTTP.Free; end; end; |
Прием – пример из проекта
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
procedure TRP.SendSms(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); var s: TSMSC; phone: string; msg: string; begin s := TSMSC.Create; try try phone := ARequestInfo.Params.Values['phone']; msg := TNetEncoding.URL.Base64.Decode((ARequestInfo.Params.Values['message'])); s.send_sms(phone, msg); ResponseOK(AResponseInfo); except on E: Exception do ResponseInternalServerError(AResponseInfo, e.Message); end; finally s.Free; end; end; |