您的位置:首页 > 理论基础 > 计算机网络

UTF-8 response of TIdHTTPServer with Free Pascal

2016-02-19 15:14 706 查看
原链接:原链接

问题 (Question)

This code starts a HTTP server which listens for requests on port 8080. When compiled with Delphi 2009, the Chinese text is rendered correctly. With Free Pascal 2.6.0 however, the browser displays
中文
instead
of
中文
.

What is the correct way to write Unicode / UTF-8 HTTP responses with Indy and Free Pascal?

这段代码启动HTTP服务器在端口8080上侦听请求。在Delphi 2009中编译时,中文文本正确呈现。然而,与自由帕斯卡2.6.0浏览器显示
中文
而不是
中文
.

正确的方法是什么写Unicode utf - 8 / HTTP响应与印第安纳·琼斯和帕斯卡有空吗?
program IdHTTPUnicode;

{$APPTYPE CONSOLE}

uses
IdHTTPServer, IdCustomHTTPServer, IdContext, IdSocketHandle, IdGlobal,
SysUtils;

type
TMyServer = class (TIdHTTPServer)
public
procedure InitComponent; override;
procedure DoCommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo;
AResponseInfo: TIdHTTPResponseInfo); override;
end;

procedure Demo;
var
Server: TMyServer;
begin
Server := TMyServer.Create(nil);
try
try
Server.Active := True;
except
on E: Exception do
begin
WriteLn(E.ClassName + ' ' + E.Message);
end;
end;
WriteLn('Hit any key to terminate.');
ReadLn;
finally
Server.Free;
end;
end;

procedure TMyServer.InitComponent;
var
Binding: TIdSocketHandle;
begin
inherited;

Bindings.Clear;
Binding := Bindings.Add;
Binding.IP := '127.0.0.1';
Binding.Port := 8080;
Binding.IPVersion := Id_IPv4;
end;

procedure TMyServer.DoCommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
const
UNI = '中文';
begin
AResponseInfo.ContentText := '<html>' + UNI + '</html>';
AResponseInfo.ContentType := 'text/html';
AResponseInfo.CharSet := 'UTF-8';
end;

begin
Demo;
end.


在调试器中,我可以看到,TIdIOHandler不同的代码的方法。免费写执行,帕斯卡,STRING_IS_ANSI定义:

procedure TIdIOHandler.Write(const AOut: string; AByteEncoding: TIdTextEncoding = nil
{$IFDEF STRING_IS_ANSI}; ASrcEncoding: TIdTextEncoding = nil{$ENDIF}
);
begin
if AOut <> '' then begin
AByteEncoding := iif(AByteEncoding, FDefStringEncoding);
{$IFDEF STRING_IS_ANSI}
ASrcEncoding := iif(ASrcEncoding, FDefAnsiEncoding, encOSDefault);
{$ENDIF}
Write(
ToBytes(AOut, -1, 1, AByteEncoding
{$IFDEF STRING_IS_ANSI}, ASrcEncoding{$ENDIF}
)
);
end;
end;


FreePascal字符串是utf - 16编码不像他们在Delphi 2009 +。FreePascal,在Delphi 2007和以前的版本中,您的代码需要考虑实际的字符串编码。这就是为什么赛车公开其他Ansi-based参数/属性为这些平台。

当TIdHTTPServer写出ContentText使用TIdIOHandler.Write(),ASrcEncoding参数没有使用unicode平台上,所以你必须使用TIdIOHandler.DefAnsiEncoding财产而不是让Write()知道的编码ContentText如:


procedure TMyServer.DoCommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
const
UNI: WideString = '中文';
begin
AResponseInfo.ContentText := UTF8Encode('<html>' + UNI + '</html>');
AResponseInfo.ContentType := 'text/html';

// this tells TIdHTTPServer what to encode bytes to during socket transmission
AResponseInfo.CharSet := 'utf-8';

// this tells TIdHTTPServer what encoding the ContentText is using
// so it can be decoded to Unicode prior to then being charset-encoded
// for output. If the input and output encodings are the same, the
// Ansi string data gets transmitted as-is without decoding/reencoding...
AContext.Connection.IOHandler.DefAnsiEncoding := IndyUTF8Encoding;
end;


在现代FreePascal默认字符串是utf - 8,除非你调整copil选项。

因此似乎在
iif(ASrcEncoding, FDefAnsiEncoding, encOSDefault);
的价值
encOSDefault
是错误的。你可以解决它的检测在印第安纳·琼斯来源如果你喜欢或我想更好的设置
DefAnsiEncoding
:= 'utf-8';
(由RFC拖欠的低)

在安全方面你可以检查utf - 8模式在程序开始。设置一些非拉丁常数(如中国的事情,或希腊或斯拉夫字母——不管)和检查如果是UTF8:http://compaspascal.blogspot.ru/2009/03/utf-8-automatic-detection.html

不过总的来说,我认为你可能会发现一些库,关心FPC和Linux比印第安纳·琼斯。印地赛车似乎我停滞不前,甚至遗弃在Delphi旁边。也许
Synopse
mORMot
(寻找DataSnap性能测试文章)可以帮助你或者一些附带的库
CodeTyphon
发行版。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: