擷取 HTTP 標頭
本教學課程說明如何從 HTTP 要求擷取標頭資訊。
實作步驟
有兩種方式可以擷取標頭資訊:
- 使用與應用程式所需的 HTTP 標頭相關聯的 查詢資訊旗標 常數之一。
- 使用 HTTP_QUERY_CUSTOM 屬性旗標,並傳遞 HTTP 標頭的名稱。
在內部使用與應用程式所需 HTTP 標頭相關聯的常數可以更快,但可能存在沒有常數與其相關聯的 HTTP 標頭。 在這些情況下,可以使用使用 HTTP_QUERY_CUSTOM 屬性旗標的方法。
這兩種方法都會使用 HttpQueryInfo 函式。 HttpQueryInfo 使用 HTTP 要求所在的 HINTERNET 句柄,一個屬性,一個緩衝區,一個包含緩衝區大小的 DWORD 值,以及一個索引值。 修飾詞也可以新增至傳遞至 HttpQueryInfo 的屬性,以指出應該傳回數據的格式。
使用常數擷取標頭
若要使用 HttpQueryInfo 函式,使用常數擷取 HTTP 標頭,請遵循下列步驟:
- 呼叫 HTTPQueryInfo,使用 Attributes 清單中的一個常數、NULL 緩衝區,以及將緩衝區大小設定為零的變數。 此外,如果您的應用程式需要特定格式的數據,您可以從 修飾詞 清單中新增常數。
- 如果要求的 HTTP 標頭存在,HttpQueryInfo 的呼叫應該會失敗,GetLastError 應該傳回ERROR_INSUFFICIENT_BUFFER,而針對 lpdwBufferLength 參數傳遞的變數應該設定為所需的位元組數。
- 分配具有所需位元組數目的緩衝區。
- 請重試呼叫 HttpQueryInfo。
下列範例示範使用 HTTP_QUERY_RAW_HEADERS_CRLF 常數來呼叫 HttpQueryInfo,這是要求所有傳回 HTTP 標頭的特殊值。
// Retrieving Headers Using a Constant
BOOL SampleCodeOne(HINTERNET hHttp)
{
LPVOID lpOutBuffer=NULL;
DWORD dwSize = 0;
retry:
// This call will fail on the first pass, because
// no buffer is allocated.
if(!HttpQueryInfo(hHttp,HTTP_QUERY_RAW_HEADERS_CRLF,
(LPVOID)lpOutBuffer,&dwSize,NULL))
{
if (GetLastError()==ERROR_HTTP_HEADER_NOT_FOUND)
{
// Code to handle the case where the header isn't available.
return TRUE;
}
else
{
// Check for an insufficient buffer.
if (GetLastError()==ERROR_INSUFFICIENT_BUFFER)
{
// Allocate the necessary buffer.
lpOutBuffer = new char[dwSize];
// Retry the call.
goto retry;
}
else
{
// Error handling code.
if (lpOutBuffer)
{
delete [] lpOutBuffer;
}
return FALSE;
}
}
}
if (lpOutBuffer)
{
delete [] lpOutBuffer;
}
return TRUE;
}
使用HTTP_QUERY_CUSTOM擷取標頭
若要使用 HttpQueryInfo 函式,使用 HTTP_QUERY_CUSTOM 擷取 HTTP 標頭,請遵循下列步驟:
- 配置夠大的緩衝區,以保存 HTTP 標頭的字串名稱。
- 將 HTTP 標頭的字串名稱寫入緩衝區。
- 使用 HTTP_QUERY_CUSTOM呼叫 HttpQueryInfo、包含 HTTP 標頭字串名稱的緩衝區,以及保留緩衝區大小的變數。 此外,如果您的應用程式需要特定格式的數據,您可以從 修飾詞 清單中新增常數。
- 如果呼叫 HttpQueryInfo 失敗,且 GetLastError 傳回ERROR_INSUFFICIENT_BUFFER,請重新配置具有所需位元組數目的緩衝區。
- 再次將 HTTP 標頭的字串名稱寫入緩衝區。
- 請重試呼叫 HttpQueryInfo。
下列範例示範呼叫 HttpQueryInfo,使用 HTTP_QUERY_CUSTOM 常數來要求 Content-Type HTTP 標頭。
// Retrieving Headers Using HTTP_QUERY_CUSTOM
BOOL SampleCodeTwo(HINTERNET hHttp)
{
DWORD dwSize = 20;
LPVOID lpOutBuffer = new char[dwSize];
StringCchPrintfA((LPSTR)lpOutBuffer,dwSize,"Content-Type");
retry:
if(!HttpQueryInfo(hHttp,HTTP_QUERY_CUSTOM,
(LPVOID)lpOutBuffer,&dwSize,NULL))
{
if (GetLastError()==ERROR_HTTP_HEADER_NOT_FOUND)
{
// Code to handle the case where the header isn't available.
delete [] lpOutBuffer;
return TRUE;
}
else
{
// Check for an insufficient buffer.
if (GetLastError()==ERROR_INSUFFICIENT_BUFFER)
{
// Allocate the necessary buffer.
delete [] lpOutBuffer;
lpOutBuffer = new char[dwSize];
// Rewrite the header name in the buffer.
StringCchPrintfA((LPSTR)lpOutBuffer,
dwSize,"Content-Type");
// Retry the call.
goto retry;
}
else
{
// Error handling code.
delete [] lpOutBuffer;
return FALSE;
}
}
}
return TRUE;
}
注意
WinINet 不支援伺服器實作。 此外,不應在服務平台中使用。 針對伺服器實作或服務,請使用 Microsoft Windows HTTP 服務 (WinHTTP)。