indy httpserver 接收URL包含中文参数乱码的问题
在测试TIdHttpServer的时候,发现浏览器提交的URL包含中文时会乱码,我用的是XE7 UPDATE1,INDY是10。
procedure TForm1.idhtpsrv1CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo;
AResponseInfo: TIdHTTPResponseInfo);
在这事件处理中文时,AResponseInfo好办,只要设置下
AResponseInfo.ContentType := 'text/html';
AResponseInfo.CharSet := 'utf-8';
浏览器就能正确显现中文。
对于 ARequestInfo,回头想想一开始决解方向就错了,不要想着各种编码转换,实际到这里,INDY已经把编码转换好了,因为到这里处理的文本,
ARequestInfo.Params.Text已经是string类型了(UNICODE)。网上说是改INDY的源码,因为没地方设置TIdHTTPRequestInfo编码属性。
改动的是IdCustomHTTPServer.pas的 TIdHTTPRequestInfo.DecodeAndSetParams(const AValue: String)方法:
procedure TIdHTTPRequestInfo.DecodeAndSetParams(const AValue: String); var i, j : Integer; s: string; LEncoding: IIdTextEncoding; begin // Convert special characters // ampersand '&' separates values {Do not Localize} Params.BeginUpdate; try Params.Clear; CharSet := 'utf-8'; //添加这一行 // which charset to use for decoding query string parameters. We // should not be using the 'Content-Type' charset for that. For // 'application/x-www-form-urlencoded' forms, we should be, though... LEncoding := CharsetToEncoding(CharSet); i := 1; while i <= Length(AValue) do begin j := i; while (j <= Length(AValue)) and (AValue[j] <> '&') do {do not localize} begin Inc(j); end; s := Copy(AValue, i, j-i); // See RFC 1866 section 8.2.1. TP s := StringReplace(s, '+', ' ', [rfReplaceAll]); {do not localize} Params.Add(TIdURI.URLDecode(s, LEncoding)); i := j + 1; end; finally Params.EndUpdate; end; end;
然后重新编译IndyProtocols包,注意bpl文件放在bin下,dcu和dcp文件放在Lib下的各个相应目录下(就是win32/win64, debug/release)
测试代码:
procedure TForm1.idhtpsrv1CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); begin AResponseInfo.ContentType := 'text/html'; AResponseInfo.CharSet := 'utf-8'; mmo1.Lines.Add('====================='); mmo1.Lines.Add('Document:'); mmo1.Lines.Add(''); mmo1.Lines.Add(ARequestInfo.Params.Text); mmo1.Lines.Add('p1: '+ ARequestInfo.Params.Values['p1']); mmo1.Lines.Add('p2: '+ ARequestInfo.Params.Values['p2']); AResponseInfo.ContentText := '是中文吧'; // 'HttpServer OK'; end;
浏览器URL:http://127.0.0.1:8000/test?p1=中文&p2=ghg
用 Chrome,edge,360浏览器测试正确。