Retrieving HTTP Headers

This tutorial describes how to retrieve header information from HTTP requests.

Implementation Steps

There are two ways to retrieve the header information:

  • Use one of the Query Info Flag constants associated with the HTTP header that your application needs.
  • Use the HTTP_QUERY_CUSTOM attribute flag and pass the name of the HTTP header.

Using the constant associated with the HTTP header that your application needs is faster internally, but there might be HTTP headers that do not have a constant associated with them. For those cases, the method using the HTTP_QUERY_CUSTOM attribute flag is available.

Both methods use the HttpQueryInfo function. HttpQueryInfo takes the HINTERNET handle on which the HTTP request was made, one attribute, a buffer, a DWORD value that contains the buffer size, and an index value. A modifier can also be added to the attribute passed to HttpQueryInfo to indicate in what format the data should be returned.

Retrieving Headers Using a Constant

To use the HttpQueryInfo function to retrieve an HTTP header using a constant, follow these steps:

  1. Call HttpQueryInfo with a constant from the Attributes list, a NULL buffer, and the variable that holds the buffer size set to zero. Also, if your application needs the data in a particular format, you can add a constant from the Modifiers list.
  2. If the requested HTTP header exists, the call to HttpQueryInfo should fail, GetLastError should return ERROR_INSUFFICIENT_BUFFER, and the variable passed for the lpdwBufferLength parameter should be set to the number of bytes required.
  3. Allocate a buffer with the number of bytes required.
  4. Retry the call to HttpQueryInfo.

The following sample demonstrates a call to HttpQueryInfo using the HTTP_QUERY_RAW_HEADERS_CRLF constant, which is a special value that requests all of the returned HTTP headers.

// 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;
}

Retrieving Headers Using HTTP_QUERY_CUSTOM

To use the HttpQueryInfo function to retrieve an HTTP header using HTTP_QUERY_CUSTOM, follow these steps:

  1. Allocate a buffer that is large enough to hold the string name of the HTTP header.
  2. Write the string name of the HTTP header into the buffer.
  3. Call HttpQueryInfo with HTTP_QUERY_CUSTOM, the buffer that contains the string name of the HTTP header, and the variable that holds the buffer size. Also, if your application needs the data in a particular format, you can add a constant from the Modifiers list.
  4. If the call to HttpQueryInfo fails and GetLastError returns ERROR_INSUFFICIENT_BUFFER, reallocate a buffer with the number of bytes required.
  5. Write the string name of the HTTP header into the buffer again.
  6. Retry the call to HttpQueryInfo.

The following sample demonstrates a call to HttpQueryInfo using the HTTP_QUERY_CUSTOM constant to request the Content-Type HTTP header.

// 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;
}

Note

WinINet does not support server implementations. In addition, it should not be used from a service. For server implementations or services use Microsoft Windows HTTP Services (WinHTTP).