【问题标题】:How to get all request headers?如何获取所有请求标头?
【发布时间】:2013-10-25 03:51:55
【问题描述】:

如何获取带有OIBindInfoIWinInetHttpInfo 的所有请求标头?我在Start 中使用它,但变量HeadersRequestHeaders 始终为空?

使用OIBindInfo

function THandler.Start(szUrl: PWideChar; OIProtSink:
IInternetProtocolSink; OIBindInfo: IInternetBindInfo; grfPI, dwReserved:
DWORD): HResult; stdcall;
var
    dwSize: ULONG;
    pszHeaders: POleStr;
    Headers: String;
begin
    OIBindInfo.GetBindString(BINDSTRING_HEADERS, @pszHeaders, 1, dwsize)
    Headers := PWideChar(pszHeaders); // weird result of Headers = ჸ
    CoTaskMemFree(pszHeaders);
    pszHeaders := nil;
    Result := INET_E_USE_DEFAULT_PROTOCOLHANDLER;
end;

使用IWinInetHttpInfo

type
  THandler = class(TComObject, IInternetProtocol, IWinInetHttpInfo)
    private
      ServiceProvider: IServiceProvider;
      WinInetHttpInfo: IWinInetHttpInfo;
      URL: String;
      RequestHeaders: String;
      function QueryInfoEx(dwOption: DWORD; var Info: string): Boolean;
    protected
      function Start(szUrl: PWideChar; OIProtSink: IInternetProtocolSink;
        OIBindInfo: IInternetBindInfo; grfPI, dwReserved: DWORD): HResult; stdcall;
      function Continue(const ProtocolData: TProtocolData): HResult; stdcall;
      function Abort(hrReason: HResult; dwOptions: DWORD): HResult; stdcall;
      function Terminate(dwOptions: DWORD): HResult; stdcall;
      function Suspend: HResult; stdcall;
      function Resume: HResult; stdcall;
      function Read(pv: Pointer; cb: ULONG; out cbRead: ULONG): HResult; stdcall;
      function Seek(dlibMove: LARGE_INTEGER; dwOrigin: DWORD;
        out libNewPosition: ULARGE_INTEGER): HResult; stdcall;
      function LockRequest(dwOptions: DWORD): HResult; stdcall;
      function UnlockRequest: HResult; stdcall;
      function QueryInfo(dwOption: DWORD; Buffer: Pointer; var cbBuf, dwFlags, dwReserved: DWORD): HResult; stdcall;
      function QueryOption(dwOption: DWORD; Buffer: Pointer; var cbBuf: DWORD): HResult; stdcall;
  end;

function THandler.QueryInfoEx(dwOption: DWORD; var Info: string): Boolean;
var
  Buf: array[0..INTERNET_MAX_PATH_LENGTH] of AnsiChar;
  BufLength, dwReserved, dwFlags: Cardinal;
begin
    dwReserved := 0;
    dwFlags := 0;
    BufLength := INTERNET_MAX_PATH_LENGTH + 1;
    Result := not Boolean(WinInetHttpInfo.QueryInfo(dwOption, @Buf, BufLength, dwFlags, dwReserved));
    if Result then 
    Info := string(Buf);
end;

function THandler.Start(szUrl: PWideChar; OIProtSink:
IInternetProtocolSink; OIBindInfo: IInternetBindInfo; grfPI, dwReserved:
DWORD): HResult; stdcall;
begin
  OIProtSink.QueryInterface(IServiceProvider, ServiceProvider);
  OIProtSink.QueryInterface(IWinInetHttpInfo, WinInetHttpInfo);
  QueryInfoEx(HTTP_QUERY_RAW_HEADERS, RequestHeaders); // empty RequestHeaders
  Result := INET_E_USE_DEFAULT_PROTOCOLHANDLER;
end;

两者都不起作用!

【问题讨论】:

  • 尝试使用 POleStr 而不是 POleStrArray。

标签: delphi com twebbrowser


【解决方案1】:

您没有查看GetBindString() 的返回值来确保它输出任何数据。

如果您要检索特定标头,则使用单个 POleStr 很好,例如:

function THandler.Start(szUrl: PWideChar; OIProtSink: IInternetProtocolSink; OIBindInfo: IInternetBindInfo; grfPI, dwReserved: DWORD): HResult; stdcall;
var
  MimeType: POleStr;
  Fetched: ULONG;
begin
  if Succeeded(OIBindInfo.GetBindString(BINDSTRING_POST_DATA_MIME, @MimeType, 1, Fetched)) then
  begin
    // use MimeType as needed...
    CoTaskMemFree(MimeType);
  end;
  Result := INET_E_USE_DEFAULT_PROTOCOLHANDLER;
end;

但是,您正在尝试检索多个标头,因此您需要使用数组来代替:

function THandler.Start(szUrl: PWideChar; OIProtSink: IInternetProtocolSink; OIBindInfo: IInternetBindInfo; grfPI, dwReserved: DWORD): HResult; stdcall;
var
  Headers: array[0..255] of POleStr;
  Fetched, I: ULONG;
begin
  Fetched := 0;
  if Succeeded(OIBindInfo.GetBindString(BINDSTRING_HEADERS, @Headers[0], Length(Headers), Fetched)) then
  begin
    if Fetched > 0 then
    begin
      for I := 0 to Fetched-1 do
      begin
        // use Headers[I] as needed...
        CoTaskMemFree(Headers[I]);
      end;
    end;
  end;
  Result := INET_E_USE_DEFAULT_PROTOCOLHANDLER;
end;

话虽如此,MSDN says BINDSTRING_HEADERS 是“当前不支持”。

【讨论】:

  • 为什么在GetBindString 被调用之前就分配了Headers?你真的测试过这段代码吗?因为这不适用于任何标志。请更新您的代码。
  • Headers 是一个指针数组。 GetBindString() 不分配新数组,它只是填充给定的现有数组,这就是为什么您还必须传入数组长度的原因。我不知道是否可以查询存在多少标头,以便可以动态调整数组的大小。不,我没有尝试代码,它是基于我找到的其他示例。
  • 早在GetBindString 被称为之前,它就充满了奇怪的字符。
  • 那是因为数组是在堆栈上分配的,所以它会使用堆栈的该部分上已经存在的任何随机数据进行初始化。这很好。你告诉GetBindString()数组中有多少个槽,它返回它填充了多少槽,其余的无关紧要。
猜你喜欢
  • 2011-04-22
  • 2014-05-02
  • 2011-10-15
  • 2018-02-27
  • 1970-01-01
  • 1970-01-01
  • 2016-03-21
  • 2013-11-16
相关资源
最近更新 更多