Visual C++ 6 Unleashed

Visual C++ 6 Unleashed

By MICKEY WILLIAMS and David Bennett

HTTP Client Functions

As you saw earlier, you can use InternetOpenUrl() to make simple HTTP requests to retrieve files; however, for more complicated operations, you need to use the HTTP- specific functions that you will look at here. These functions require an HINTERNET parameter, which is a connection handle returned from InternetConnect().

In this section, you will see how to use the WinInet HTTP functions to create a request, send it to the server, and retrieve the results. You also will look at some special functions used to work with cookies and the persistent cache.

HTTP Requests

Several steps are involved in sending an HTTP request and retrieving its results. To start with, a new request is created with HttpOpenRequest(). You then can modify the headers for the request with HttpAddRequestHeaders() before sending the request to the server with HttpSendRequest().

Creating an HTTP Request

A new HTTP request is created by calling HttpOpenRequest():

HINTERNET HttpOpenRequest(HINTERNET hHttpSession, LPCTSTR lpszVerb,
    LPCTSTR lpszObjectName, LPCTSTR lpszVersion,
    LPCTSTR lpszReferer, LPCTSTR FAR * lpszAcceptTypes,
    DWORD dwFlags, DWORD dwContext);

The handle passed in hHttpSession is returned by a call to InternetConnect().

The two most important elements of an HTTP request are the object to act on, passed in lpszObjectName, and the verb to use, passed in lpszVerb, which specifies the action the server should perform on the object.

The string containing the object name, which is passed by lpszObjectName, generally contains a filename to retrieve.

The lpszVerb parameter points to a string containing the verb to use for the request. You can specify a NULL pointer here to use the GET default verb, or you can pass a pointer to a string for the following verbs:

If you are using a version of HTTP other than 1.0, you may specify that version in a string at lpszVersion. If this value is NULL, the default of HTTP/1.0 is used.

The lpszAcceptTypes parameter is used to specify the type of information that the client application will accept. lpszAcceptTypes is a pointer to a null-terminated array of pointers to strings containing data types that will be accepted, such as image/jpeg or audio/*. If lpszAcceptTypes is NULL, the request will use text/* to accept only text files.

You also may choose to specify the URL of a referring page in lpszReferer, a context value for asynchronous I/O in dwContext, or other options for the call in dwFlags. HttpOpenRequest() accepts the same flags you saw for InternetOpenUrl() earlier.

Upon successful completion, HttpOpenRequest() returns an HINTERNET handle for the request. This handle then is passed to calls such as HttpAddRequestHeaders(), HttpSendRequest(), and HttpQueryInfo().

Request Headers

HTTP requests can have a variety of different headers attached to them to clarify just how a particular request is to be satisfied. You can use the WinInet HttpAddRequestHeaders() function to add headers, as well as to modify or remove existing headers:

BOOL HttpAddRequestHeaders(HINTERNET hHttpRequest, LPCTSTR lpszHeaders,
    DWORD dwHeadersLength, DWORD dwModifiers);

The operation performed by HttpAddRequestHeaders() is specified by the value passed in dwModifiers, which can have a combination of the following values:

The headers to be added are passed in lpszHeaders, which points to a string containing individual headers separated by a CR/LF pair. The length of this string is passed in dwHeadersLength, which may be -1L if the lpszHeaders string is null-terminated.

Sending an HTTP Request

An HTTP request, as specified by an HINTERNET created by HttpOpenRequest(), is sent to the server with a call to HttpSendRequest():

BOOL HttpSendRequest(HINTERNET hHttpRequest, LPCTSTR lpszHeaders,
    DWORD dwHeadersLength, LPVOID lpOptional, DWORD dwOptionalLength);

HttpSendRequest() enables you to specify any additional headers to send with the request in lpszHeaders, with the length of the string in dwHeadersLength.

You also can specify any additional data to be sent immediately after the request headers by passing a pointer to the data in lpOptional and its length in dwOptionalLength. This normally is used only with the POST and PUT operations, which send data to the server.

HttpSendRequest() will send the request to the server and read the status code and response headers from the server. You can access the information in the response headers with HttpQueryInfo(). You can read the body of any data returned by using the InternetReadFile() function.

Handling HttpSendRequest() Errors

If HttpSendRequest() completes successfully, it returns TRUE; otherwise, it returns FALSE, and you should call GetLastError() to retrieve the specific error code. In addition, the WinInet API provides a special function for dealing with errors in HttpSendRequest(): InternetErrorDlg(). You also can use it to detect errors in the response headers that do not result in failure of the HttpSendRequest() call. It presents a dialog box to the user, detailing the error and requesting input about how to handle the error.

The prototype for InternetErrorDlg() follows:

DWORD InternetErrorDlg(HWND hWnd, HINTERNET hInternet,
    DWORD dwError, DWORD dwFlags, LPVOID *lppvData);

The hWnd parameter gives the parent of the dialog box to be created, and the handle in hInternet is the handle of the HTTP request, as returned from HttpOpenRequest() and used in the HttpSendRequest() call.

The dwError parameter specifies the error that should be handled by the dialog box. This can have the following values:

The dwFlags parameter specifies what action the function will take in handling an error. The following values are supported:

The function of the lppvData parameter has not yet been defined, so a value of NULL should be passed.

Retrieving Response Information

You can access information that the server sends back to a client application in the response headers by using the HttpQueryInfo() function:

BOOL HttpQueryInfo(HINTERNET hHttpRequest, DWORD dwInfoLevel,
    LPVOID lpvBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex);

The hHttpRequest parameter should be a handle returned from HttpOpenRequest().

The dwInfoLevel parameter specifies what information to return and how to return it. This value is formed by combining one of these indexes with one of the flags in this list:

The indexes listed can be combined with one of the following flags, which specify how the requested data will be returned:

The information that is returned is written at lpvBuffer, and its length is written at lpdwBufferLength.

The lpdwIndex parameter is used to return information on multiple headers with the same name. On calling HttpQueryInfo(), you can specify the 0-based index of the header to retrieve in the DWORD at lpdwIndex. Upon return, the value at lpdwIndex is set to the index of the next matching header, or ERROR_HTTP_HEADER_NOT_FOUND if no more matching headers are found.

Getting Your Hands in the Cookie Jar

Many Internet applications use cookies, which can store on the local machine bits of data associated with a particular URL. In most cases, cookies are used to maintain state information for HTTP sessions. Cookies are stored in the windows\cookies directory on Win95 or the winnt\cookies directory on WinNT.

You can add a new cookie to the local system with the InternetSetCookie() function:

BOOL InternetSetCookie(LPCSTR lpszUrlName,
    LPCSTR lpszCookieName, LPCSTR lpszCookieData);

This function takes pointers to three null-terminated strings: lpszUrlName points to the URL with which to associate the cookie, lpszCookieName points to the name of the cookie, and lpszCookieData points to the string that will be saved for the new cookie.

You can retrieve data stored in a cookie for a given URL, or its parent URLs, by calling InternetGetCookie():

BOOL InternetGetCookie(LPCSTR lpszUrlName, LPCSTR lpszCookieName,
    LPSTR lpszCookieData, LPDWORD  lpdwSize);

This function tries to find a cookie named in lpszCookieName that is associated with the URL in lpszUrlName or its parent URLs and returns any data found at lpszCookieData and its length at lpdwSize.

Working with the Cache

Many of the WinInet functions you have looked at so far in this chapter can use the persistent cache to store received data to disk, depending on certain flags. This capability enables applications such as browsers to retrieve frequently accessed data more efficiently than having to download it each time.

The WinInet API provides the following functions, which enable you to work with the cache more directly from within your applications:

Share ThisShare This

Informit Network