WinInet HttpQueryInfo 可以返回原始字节吗? (带有 unicode 字符的 HTTP 标头)

Posted

技术标签:

【中文标题】WinInet HttpQueryInfo 可以返回原始字节吗? (带有 unicode 字符的 HTTP 标头)【英文标题】:Can WinInet HttpQueryInfo return raw bytes? (HTTP Headers with unicode characters) 【发布时间】:2012-09-19 01:22:59 【问题描述】:

内置例程 HttpQueryInfo 返回一个字符串,而不是实际字节。通常这不是问题。

但是,最近我开始遇到服务器发出重定向的问题,其中位置标头字段包含包含非百分比编码的 unicode/或?人物。有什么办法吗?

        var
          vContent_Wide: WideString;
        begin 
          vBufferSize := 4096;
          GetMem(vBufferPtr, vBufferSize);
          while True do
          begin
            TmpFakeCardinal := 0;
            vErrorNone := HttpQueryInfo(
              hHttpOpen_Request,
              HTTP_QUERY_RAW_HEADERS_CRLF,
              vBufferPtr,
              vBufferSize,
              TmpFakeCardinal
            );
            if (vErrorNone = False) then
              begin
                vErrorID := GetLastError;
                if (vErrorID = ERROR_INSUFFICIENT_BUFFER) then
                  begin
                    FreeMem(vBufferPtr);
                    GetMem(vBufferPtr, vBufferSize);
                  end
                else Break;
              end
            else
              begin
                vContent_Wide := PWideChar(vBufferPtr); 
                Result := vContent_Wide;
                Break;
              end
            ;
          end;
          FreeMem(vBufferPtr, vBufferSize);

【问题讨论】:

请编辑您的问题:添加您使用的某个 Delphi 版本的标签。不清楚是调用HttpQueryInfoA还是HttpQueryInfoW 什么是 vContent_Native?什么是 msxCopyPCharToStr ?你没有显示任何声明! 代码中的注释说明了。 Delphi 2007 将其映射到 HttpQueryInfoA,而 Delphi XE2(所有 unicode 版本)将其映射到 HttpQueryInfoW。 (而vContent_Native是对应的字符串类型) 但是我现在已经更正了代码以假设 Delphi XE2。 (但是API调用的“A”和“W”版本都存在这个问题。我来回做了很多实验) Indy 的TIdHTTP 组件使用IOHandler.DefStringEncoding 属性来决定使用哪个字符集来解码HTTP 标头。如果您想使用不同的解码字符集,您可以在发送请求之前设置DefStringEncoding 属性。 【参考方案1】:

URI 不支持未编码的 Unicode 字符。如果服务器在 Location 标头中发送非百分比编码的 Unicode 字符串,则服务器有问题,需要修复,因为这明显违反了 RFC 2616 section 14.30。我的猜测是服务器实际上发送的是未映射的 IRI (RFC 3987) 而不是 URI (RFC 3986)。 HTTP 不支持直接使用 IRI,它们必须映射到 URI(RFC 3987 定义了如何做到这一点)。

话虽如此,请检查将dwInfoLevel 参数设置为HTTP_QUERY_CUSTOM 是否允许HttpQueryInfo() 返回标头的原始字节。如果没有,那么您将无法将 WinInet 用于那些出现故障的服务器,因为 WinInet API 中没有其他函数可以访问 HTTP 标头。您必须找到另一个支持您需要的 HTTP 库,否则您可以下拉到 TCP/IP 层并在您自己的代码中手动实现 HTTP 协议。

【讨论】:

感谢您的回复雷米。我现在已经投票了,我希望今晚或明天晚些时候将其标记为已接受的答案:) 我没有成功使用 HTTP_QUERY_CUSTOM,但我现在正在测试你们关于 Indy 的 cmets。 解决方案最终是您在评论中其他地方建议的:将 Indy 的 TIdHTTP IOHandler.DefStringEncoding 设置为 UTF-8。这解决了两个不同客户的问题

以上是关于WinInet HttpQueryInfo 可以返回原始字节吗? (带有 unicode 字符的 HTTP 标头)的主要内容,如果未能解决你的问题,请参考以下文章

您可以传递给 Wininet 函数 HttpOpenRequest 的最大 URL 长度是多少?

WebBrowser 控件和 Wininet API

Wininet 缓存包装器

以编程方式清除 WinInet DNS 缓存

WinInet C++ ftp 模板?

通过 WinInet 下载数据