【问题标题】:Indy HTTP Server URL-encoded requestIndy HTTP Server URL 编码请求
【发布时间】:2014-07-21 09:32:18
【问题描述】:

当 Indy HTTP 服务器收到带有 /find?location=%D1%82%D0%B5%D1%81%D1%82(utf-8 url 编码值)之类 url 的请求时,“location”字段在requestinfo 的 Params 具有不可读的值 ÑеÑÑ。

如何获得可读值? Indy HTTPServer 版本 10.6.0.4975

【问题讨论】:

    标签: http encoding indy


    【解决方案1】:

    TIdHTTPServer 当前使用Content-Type 请求标头中指定的字符集解析输入参数,如果没有指定字符集,则使用 Indy 的 8 位编码。这是TIdHTTPServer 的已知限制,因为目前没有选项告诉它使用用户定义的字符集解码参数。因此,您将不得不手动解析ARequestInfo.QueryParams 和/或ARequestInfo.UnparsedParams 属性,例如通过在其AByteEncoding 参数中使用UTF-8 编码直接调用TIdURI.URLDecode(),例如:

    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;
        LEncoding := CharsetToEncoding(ARequestInfo.CharSet);
      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 月起,如果 Content-Type 标头中未指定字符集,TIdHTTPServer 现在默认使用 UTF-8 解析输入参数。因此不再需要上述解决方法。

    【讨论】:

    • GIdDefaultTextEncoding:=encUTF8 无效。
    • 对不起,我的错。我没有注意到CharsetToEncoding()(DecodeAndSetParams() 在内部使用)强制 8 位作为空白字符集,而不是使用GIdDefaultTextEncoding。我已经相应地更新了我的答案。
    • 如果客户端发送带有 url 参数的 urlencoded 后表单,您的代码将无法正常工作。但谢谢你的想法
    • URL 参数和表单参数应该分开处理。 TIdHTTPServer 将它们合并在一起实际上是一个错误,这将在 Indy 11 中得到纠正。如果你真的需要,没有什么能阻止你在上面的代码中将它们合并在一起。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多