检索 HTTP 标头

本教程介绍如何从 HTTP 请求检索标头信息。

实现步骤

可通过两种方法检索标头信息:

  • 使用与应用程序所需的 HTTP 标头关联的 查询信息标志 常量之一。
  • 使用 HTTP_QUERY_CUSTOM 属性标志并传递 HTTP 标头的名称。

使用与应用程序所需的 HTTP 标头关联的常量在内部会更快,但可能存在没有与之关联的常量的 HTTP 标头。 在这些情况下,可以使用使用 HTTP_QUERY_CUSTOM 属性标志的方法。

这两种方法都使用 HttpQueryInfo 函数。 HttpQueryInfo 采用发出 HTTP 请求的 HINTERNET 句柄、一个属性、一个缓冲区、一个包含缓冲区大小的 DWORD 值和一个索引值。 还可以将修饰符添加到传递给 HttpQueryInfo 的属性,以指示应以何种格式返回数据。

使用常量检索标头

若要使用 HttpQueryInfo 函数通过常量检索 HTTP 标头,请执行以下步骤:

  1. 使用属性列表中的常量、NULL 缓冲区和将缓冲区大小设置为零的变量调用 HttpQueryInfo。 此外,如果应用程序需要特定格式的数据,则可以从 “修饰符 ”列表中添加常量。
  2. 如果请求的 HTTP 标头存在,则对 HttpQueryInfo 的 调用应失败, GetLastError 应返回ERROR_INSUFFICIENT_BUFFER,并且为 lpdwBufferLength 参数传递的变量应设置为所需的字节数。
  3. 分配具有所需字节数的缓冲区。
  4. 重试对 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 标头,请执行以下步骤:

  1. 分配一个足够大的缓冲区,用于保存 HTTP 标头的字符串名称。
  2. 将 HTTP 标头的字符串名称写入缓冲区。
  3. 使用 HTTP_QUERY_CUSTOM 调用 HttpQueryInfo 、包含 HTTP 标头的字符串名称的缓冲区以及保存缓冲区大小的变量。 此外,如果应用程序需要特定格式的数据,则可以从 “修饰符 ”列表中添加常量。
  4. 如果对 HttpQueryInfo 的 调用失败,并且 GetLastError 返回ERROR_INSUFFICIENT_BUFFER,请使用所需的字节数重新分配缓冲区。
  5. 再次将 HTTP 标头的字符串名称写入缓冲区。
  6. 重试对 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)