delphiindy

Indy HTTP Server ARequestInfo.Params.Text Encoding Wrong


I am using Delphi 10.4.2 , Indy 10.6.2.0 .

I've tried this solutions : Indy HTTP Server URL-encoded request , but I guess I am misunderstanding something .

I get the JSON from the Web Application like this :

procedure TForm1.IdHTTPServer1CommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
  If ARequestInfo.CommandType = hcPOST then
  begin

    MyDecodeAndSetParams(ARequestInfo);

    Memo1.Lines.Add(ARequestInfo.Params.Text);
end;

I am probably doing something wrong but my result is still incorrect :

D Karlsruhe / Südweststadt, Bahnhofstraße

It should be Südweststadt and Bahnhofstraße

Please help. Thank you.


Solution

  • The decoded text you have shown is what happens when UTF-8 is misinterpreted as Latin-1/8bit. If you are using an up-to-date version of Indy, then as I stated in my answer to the post you linked to, TIdHTTPServer was updated several years ago (after 10.4.2 was released) to handle this issue, so you shouldn't need MyDecodeAndSetParams() anymore if you are using an up-to-date version of Indy.

    But, it sounds like you are using an older version and should update Indy. But, if you are stuck using an older version of Indy, then you will have to update MyDecodeAndSetParams() instead.

    Since you are processing a POST request, you are likely falling into the application/x-www-form-urlencoded portion of the code, and I'm betting that ARequestInfo.CharSet is blank, which would cause CharsetToEncoding() to fallback to Indy's 8-bit encoding instead of UTF-8.

    Try changing this line in MyDecodeAndSetParams():

    LEncoding := CharsetToEncoding(ARequestInfo.CharSet);
    

    To this instead:

    if ARequestInfo.CharSet <> '' then
      LEncoding := CharsetToEncoding(ARequestInfo.CharSet)
    else
      LEncoding := IndyTextEncoding_UTF8;
    

    (I have updated the example in my other answer)


    On a side note: TIdHTTPServer is multi-threaded, its OnCommandGet event is fired in the context of a worker thread, so you must synchronize with the main UI thread when accessing UI controls, eg:

    procedure TForm1.IdHTTPServer1CommandGet(AContext: TIdContext;
      ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
    begin
      If ARequestInfo.CommandType = hcPOST then
      begin
    
        MyDecodeAndSetParams(ARequestInfo);
    
        //Memo1.Lines.Add(ARequestInfo.Params.Text);
        TThread.Synchronize(nil,
          procedure
          begin
            Memo1.Lines.Add(ARequestInfo.Params.Text);
          end
        );
    end;