Home IdHTTPServer and IdHTTP with Encoding UTF8
Reply: 1

IdHTTPServer and IdHTTP with Encoding UTF8

Luan Xa
1#
Luan Xa Published in 2018-02-13 17:35:15Z

I am testing a localhost server using TIdHTTPServer and TIdHTTP. I am having problems with encoding UTF8 data.

client side:

procedure TForm1.SpeedButton1Click(Sender: TObject);
var
  res: string;
begin
  res:=IdHTTP1.Get('http://localhost/?msg=đi chơi thôi');
  Memo1.Lines.Add(res);
end;

Server side:

procedure TForm1.OnCommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
  Memo1.Lines.Add(ARequestInfo.Params.Values['msg']); // ?i ch?i th?i

  AResponseInfo.CharSet := 'utf-8';
  AResponseInfo.ContentText := 'chào các bạn'; // chào các b?n
end;

I want to send đi chơi thôi and receive chào các bạn. But the server receives ?i ch?i th?i and the client receives chào các b?n.

Can anyone help me?

Remy Lebeau
2#
Remy Lebeau Reply to 2018-02-13 19:26:51Z

TIdHTTP transmits the URL exactly as you give it, but http://localhost/?msg=đi chơi thôi is not a valid URL that can be transmitted as-is, as URLs can only contain ASCII characters. Unreserved ASCII characters can be used as-is, but reserved and non-ASCII characters MUST be charset-encoded into bytes and then those bytes must be url-encoded in %HH format, eg:

IdHTTP1.Get('http://localhost/?msg=%C4%91i%20ch%C6%A1i%20th%C3%B4i');

You must ensure you pass only valid url-encoded URLs to TIdHTTP.

In this example, the URL is hard-coded, but if you need something more dynamic then use the TIdURI class, eg:

IdHTTP1.Get('http://localhost/?msg=' + TIdURI.ParamsEncode('đi chơi thôi'));

TIdHTTPServer will then decode the parameter data as you are expecting. Both TIdURI and TIdHTTPServer use UTF-8 by default.

When sending a response, you are only setting a CharSet, but you are not setting a ContentType. So TIdHTTPServer will set the ContentType to 'text/html; charset=ISO-8859-1', overwriting your CharSet. You need to explicitly set the ContentType yourself so you can specify a custom CharSet, eg:

AResponseInfo.ContentType := 'text/plain';
AResponseInfo.CharSet := 'utf-8';
AResponseInfo.ContentText := 'chào các bạn';

Or:

AResponseInfo.ContentType := 'text/plain; charset=utf-8';
AResponseInfo.ContentText := 'chào các bạn';

On a side note, TIdHTTPServer is a multi-threaded component. The OnCommand... events are fired in the context of a worker thread, not the main UI thread. So accessing Memo1 directly like you are is not thread-safe. You MUST synchronize with the main UI thread in order to access UI controls safely, eg:

procedure TForm1.OnCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
  msg: string;
begin
  msg := ARequestInfo.Params.Values['msg'];
  TThread.Synchronize(nil,
    procedure
    begin
      Memo1.Lines.Add(msg);
    end
  );
  ...
end;
You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.340236 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO