2013-10-16 120 views
1

如何使用OIBindInfoIWinInetHttpInfo获取所有请求标题?我在Start中使用这个,但变量HeadersRequestHeaders总是空的?如何获取所有请求标头?

方法使用OIBindInfo:使用IWinInetHttpInfo

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; 

方法:

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; 

无论是工作!

+0

尝试使用POleStr而不是POleStrArray。 – whosrdaddy

回答

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 saysBINDSTRING_HEADERS是“目前不支持”。

+0

为什么在'GetBindString'甚至被调用之前分配'Headers'?你真的测试过这个代码吗?因为这不适用于任何国旗。请更新您的代码。 –

+0

'Headers'是一个指针数组。 'GetBindString()'不分配一个新的数组,它只是填充给定的现有数组,这就是为什么你必须传递数组长度的原因。我不知道是否有可能查询有多少标题,因此可以动态调整数组大小。不,我没有尝试过这些代码,它是基于我发现的其他例子。 –

+0

'GetBindString'甚至被称为它充满奇怪的字符。 –