检索 HTTP 标头
本教程介绍如何从 HTTP 请求检索标头信息。
实现步骤
可通过两种方法检索标头信息:
- 使用与应用程序所需的 HTTP 标头关联的 查询信息标志 常量之一。
- 使用 HTTP_QUERY_CUSTOM 属性标志并传递 HTTP 标头的名称。
使用与应用程序所需的 HTTP 标头关联的常量在内部会更快,但可能存在没有与之关联的常量的 HTTP 标头。 在这些情况下,可以使用使用 HTTP_QUERY_CUSTOM 属性标志的方法。
这两种方法都使用 HttpQueryInfo 函数。 HttpQueryInfo 采用发出 HTTP 请求的 HINTERNET 句柄、一个属性、一个缓冲区、一个包含缓冲区大小的 DWORD 值和一个索引值。 还可以将修饰符添加到传递给 HttpQueryInfo 的属性,以指示应以何种格式返回数据。
使用常量检索标头
若要使用 HttpQueryInfo 函数通过常量检索 HTTP 标头,请执行以下步骤:
- 使用属性列表中的常量、NULL 缓冲区和将缓冲区大小设置为零的变量调用 HttpQueryInfo。 此外,如果应用程序需要特定格式的数据,则可以从 “修饰符 ”列表中添加常量。
- 如果请求的 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 的调用。
下面的示例演示如何使用 HTTP_QUERY_CUSTOM 常量调用 HttpQueryInfo 以请求 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 Services (WinHTTP) 。