当 Indy
TIdHTTPServer
收到具有类似于 /find?location=%D1%82%D0%B5%D1%81%D1%82
(UTF-8 url 编码值)这样的 URL 的请求时,location
中的 RequestInfo.Params
字段具有不可读的值 теÑÑ‚
。
如何获得可读的值?
我正在使用 Indy 10.6.0.4975。
TIdHTTPServer
当前使用 Content-Type
请求标头中指定的字符集解析输入参数,如果没有指定字符集,则使用 Indy 的 8 位编码。这是 TIdHTTPServer
的已知限制,因为目前没有选项告诉它使用用户定义的字符集解码参数。因此,您必须手动解析 ARequestInfo.QueryParams
和/或 ARequestInfo.UnparsedParams
属性,例如通过在其 TIdURI.URLDecode()
参数中使用 UTF-8 编码直接调用 AByteEncoding
,例如:
procedure MyDecodeAndSetParams(ARequestInfo: TIdHTTPRequestInfo);
var
i, j : Integer;
value: s: string;
LEncoding: IIdTextEncoding;
begin
if IsHeaderMediaType(ARequestInfo.ContentType, 'application/x-www-form-urlencoded') then
begin
value := ARequestInfo.FormParams;
if ARequestInfo.CharSet <> '' then
LEncoding := CharsetToEncoding(ARequestInfo.CharSet)
else
LEncoding := IndyTextEncoding_UTF8;
end else
begin
value := ARequestInfo.QueryParams;
LEncoding := IndyTextEncoding_UTF8;
end;
ARequestInfo.Params.BeginUpdate;
try
ARequestInfo.Params.Clear;
i := 1;
while i <= Length(value) do
begin
j := i;
while (j <= Length(value)) and (value[j] <> '&') do
begin
Inc(j);
end;
s := StringReplace(Copy(value, i, j-i), '+', ' ', [rfReplaceAll]);
ARequestInfo.Params.Add(TIdURI.URLDecode(s, LEncoding));
i := j + 1;
end;
finally
ARequestInfo.Params.EndUpdate;
end;
end;
procedure TForm1.IdHTTPServer1CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
MyDecodeAndSetParams(ARequestInfo);
...
end;
更新:自 2021 年 2 月起,如果
TIdHTTPServer
标头中未指定字符集,Content-Type
现在默认使用 UTF-8 解析输入参数。因此不再需要上述解决方法。
更新:如果您仍然需要在旧版本中使用上述解决方法,我已将代码更新为现在默认为UTF-8(如果解析时
ARequestInfo.CharSet
为空)。