- Table of Contents
- Copyright
- About the Authors
- About the Contributors
- Acknowledgments
- Tell Us What You Think!
- Introduction
- How to Use This Book
- What You Need to Use This Book
- What's New in Visual C++ 6.0
- Contacting the Main Author
- Part I: Introduction
- Chapter 1. The Visual C++ 6.0 Environment
- Part II: MFC Programming
- Chapter 2. MFC Class Library Overview
- Chapter 3. MFC Message Handling Mechanism
- Chapter 4. The Document View Architecture
- Chapter 5. Creating and Using Dialog Boxes
- Chapter 6. Working with Device Contexts and GDI Objects
- Chapter 7. Creating and Using Property Sheets
- Chapter 8. Working with the File System
- Chapter 9. Using Serialization with File and Archive Objects
- Part III: Internet Programming with MFC
- Chapter 10. MFC and the Internet Server API (ISAPI)
- Chapter 11. The WinInet API
- Chapter 12. MFC HTML Support
- Part IV: Advanced Programming Topics
- Chapter 13. Using the Standard C++ Library
- Chapter 14. Error Detection and Exception Handling Techniques
- Chapter 15. Debugging and Profiling Strategies
- Chapter 16. Multithreading
- Chapter 17. Using Scripting and Other Tools to Automate the Visual C++ IDE
- Part V: Database Programming
- Chapter 18. Creating Custom AppWizards
- Chapter 19. Database Overview
- Chapter 20. ODBC Programming
- Chapter 21. MFC Database Classes
- Chapter 22. Using OLE DB
- Chapter 23. Programming with ADO
- Part VI: MFC Support for COM and ActiveX
- Chapter 24. Overview of COM and Active Technologies
- Chapter 25. Active Documents
- Chapter 26. Active Containers
- Chapter 27. Active Servers
- Chapter 28. ActiveX Controls
- Part VII: Using the Active Template Library
- Chapter 29. ATL Architecture
- Chapter 30. Creating COM Objects Using ATL
- Chapter 31. Creating ActiveX Controls Using ATL
- Chapter 32. Using ATL to Create MTS and COM+ Components
- Part VIII: Finishing Touches
- Chapter 33. Adding Windows Help
- Part IX: Appendix
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:
- GET retrieves data.
- HEAD retrieves server response headers.
- POST sends information for the server to act on.
- PUT sends information for the server to store.
- DELETE removes a resource from the server.
- LINK establishes a link between URLs.
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:
- HTTP_ADDREQ_FLAG_REPLACE replaces an existing header. If the new header value is empty, this removes an existing header.
- HTTP_ADDREQ_FLAG_ADD, when used with _REPLACE, adds the header if it does not already exist.
- HTTP_ADDREQ_FLAG_ADD_IF_NEW adds a header only if it does not already exist.
- HTTP_ADDREQ_FLAG_COALESCE combines headers with the same name into a single header.
- HTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA uses a comma to combine headers with the same name.
- HTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON uses a semicolon to combine headers of the same name.
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:
- ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR notifies the user of a zone crossing between nonsecure and secure sites.
- ERROR_INTERNET_INCORRECT_PASSWORD displays a dialog box prompting for username and password.
- ERROR_INTERNET_INVALID_CA notifies the user that a certificate for an SSL site was not found.
- ERROR_INTERNET_POST_IS_NON_SECURE displays a warning about posting data on a nonsecure connection.
- ERROR_INTERNET_SEC_CERT_CN_INVALID displays the certificate with an invalid common name and enables the user to select a certificate to respond to a server request.
- ERROR_INTERNET_SEC_CERT_DATE_INVALID notifies the user of an expired SSL certificate.
The dwFlags parameter specifies what action the function will take in handling an error. The following values are supported:
- FLAGS_ERROR_UI_FILTER_FOR_ERRORS indicates that the response headers received from the server will be scanned for errors.
- FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS indicates that the user's choices from the dialog box may result in changes to the options of the request handle passed in hInternet.
- FLAGS_ERROR_UI_FLAGS_GENERATE_DATA indicates that the function will query the handle in hInternet for any needed information.
- FLAGS_ERROR_UI_SERIALIZE_DIALOGS indicates that on a password cache entry, authentication dialog boxes are serialized.
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:
- HTTP_QUERY_ACCEPT
- HTTP_QUERY_ACCEPT_CHARSET
- HTTP_QUERY_ACCEPT_ENCODING
- HTTP_QUERY_ACCEPT_LANGUAGE
- HTTP_QUERY_ACCEPT_RANGES
- HTTP_QUERY_AGE
- HTTP_QUERY_ALLOW
- HTTP_QUERY_AUTHORIZATION
- HTTP_QUERY_CACHE_CONTROLHTTP_QUERY_CONNECTION
- HTTP_QUERY_CONTENT_BASE
- HTTP_QUERY_CONTENT_DESCRIPTION
- HTTP_QUERY_CONTENT_DISPOSTIONHTTP_QUERY_CONTENT_ENDCODING
- HTTP_QUERY_CONTENT_ID
- HTTP_QUERY_CONTENT_LANGUAGE
- HTTP_QUERY_CONTENT_LENGTH
- HTTP_QUERY_CONTENT_LOCATION
- HTTP_QUERY_CONTENT_MDS
- HTTP_QUERY_CONTENT_RANGEHTTP_QUERY_CONTENT_TRANSFER_ENCODING
- HTTP_QUERY_CONTENT_TYPE
- HTTP_QUERY_COST
- HTTP_QUERY_CUSTOM
- HTTP_QUERY_DATE
- HTTP_QUERY_DERIVED_FROM
- HTTP_QUERY_ECHO_HEADERS
- HTTP_QUERY_ECHO_HEADERS_CRLF
- HTTP_QUERY_ECHO_REPLY
- HTTP_QUERY_ECHO_REQUEST
- HTTP_QUERY_ETAG
- HTTP_QUERY_EXPECT
- HTTP_QUERY_EXPIRES
- HTTP_QUERY_FORWARDEDHTTP_QUERY_FROM
- HTTP_QUERY_HOST
- HTTP_QUERY_IF_MATCH
- HTTP_QUERY_IF_MODIFIED_SINCE
- HTTP_QUERY_IF_NONE_MATCH
- HTTP_QUERY_IF_RANGE
- HTTP_QUERY_IF_UNMODIFIED_SINCE
- HTTP_QUERY_LANGUAGE
- HTTP_QUERY_LAST_MODIFIED
- HTTP_QUERY_LINK
- HTTP_QUERY_LOCATION
- HTTP_QUERY_MAX
- HTTP_QUERY_MAX_FORWARDS
- HTTP_QUERY_MESSAGE_ID
- HTTP_QUERY_MIME_VERSION
- HTTP_QUERY_ORIG_URI
- HTTP_QUERY_PRAGMA
- HTTP_QUERY_PROXY_AUTHENTICATE
- HTTP_QUERY_PROXY_CONNECTION
- HTTP_QUERY_PUBLIC
- HTTP_QUERY_RANGE
- HTTP_QUERY_RAW_HEADERS
- HTTP_QUERY_RAW_HEADERS_CRLF
- HTTP_QUERY_REFERER
- HTTP_QUERY_REQUEST_METHOD
- HTTP_QUERY_RETRY_AFTER
- HTTP_QUERY_SERVER
- HTTP_QUERY_SET_COOKIE
- HTTP_QUERY_STATUS_CODE
- HTTP_QUERY_STATUS_TEXT
- HTTP_QUERY_TITLE
- HTTP_QUERY_TRANSFER_ENCODING
- HTTP_QUERY_UNLESS_MODIFIED_SINCE
- HTTP_QUERY_UPGRADE
- HTTP_QUERY_URI
- HTTP_QUERY_USER_AGENT
- HTTP_QUERY_VARY
- HTTP_QUERY_VERSION
- HTTP_QUERY_VIA
- HTTP_QUERY_WARNING
- HTTP_QUERY_WWW_AUTHENTICATE
- HTTP_QUERY_WWW_LINK
The indexes listed can be combined with one of the following flags, which specify how the requested data will be returned:
- HTTP_QUERY_CUSTOM enables you to specify a custom header to search for in lpvBuffer. If the header is found, its value is returned in lpvBuffer.
- HTTP_QUERY_FLAG_COALESCE indicates that headers of the same name will be combined in the returned data.
- HTTP_QUERY_FLAG_NUMBER indicates that the requested data will be returned as a DWORD.
- HTTP_QUERY_FLAG_REQUEST_HEADERS is used to query the headers used for the request, rather than the response headers.
- HTTP_QUERY_FLAG_SYSTEMTIME can be used to return date and time values as SYSTEMTIME structures, rather than strings.
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:
- CommitUrlCacheEntry() saves data to the cache.
- CreateUrlCacheEntry() creates an entry in the cache.
- CreateUrlCacheGroup() creates a group in the cache.
- DeleteUrlCacheEntry() deletes a file from the cache.
- DeleteUrlCacheGroup() deletes a group from the cache.
- FindCloseUrlCache() closes a search handle created by FindFirstUrlCacheEntry().
- FindFirstUrlCacheEntry() begins a search of cache entries.
- FindFirstUrlCacheEntryEx() is an extended version of above.
- FindNextUrlCacheEntry() retrieves individual cache entries.
- FindNextUrlCacheEntryEx() is an extended version of above.
- FreeUrlCacheSpace() frees cache space.
- FtpCommand() sends an FTP command to the FTP server.
- FtpCreateDirectory() creates a new directory on the FTP server.
- FtpDeleteFile() deletes a file on the FTP server.
- FtpFindFirstFile() searches directory specified on FTP server.
- FtpGetCurrentDirectory() returns the current directory on the FTP server.
- FtpGetFile() retrieves a file from the FTP server, creating a new local file in the process.
- FtpOpenFile() opens a file on the FTP server.
- FtpPutFile() stores a file on the FTP server.
- FtpRemoveDirectory() deletes a given directory on the FTP server.
- FtpRenameFile() renames a file on the FTP server.
- FtpSetCurrentDirectory() sets the current working directory to a new directory.
- GetUrlCacheConfigInfo() retrieves configuration information about the cache.
- GetUrlCacheEntryInfo() retrieves information about a cache entry.
- GetUrlCacheEntryInfoEx() extended version of above.
- HttpAddRequestHeaders() adds a new HTTP request header to the HTTP request handle.
- HttpEndRequest() ends the HTTP request that was released by HttpSendRequestEx.
- HttpOpenRequest() creates a new HTTP request handle.
- HttpQueryInfo() returns header information from an HTTP request.
- HttpSendRequest() sends a request to the HTTP server.
- HttpSendRequestEx() extended version of above, but allows chunked transfers.
- InternetAttemptConnect() makes an attempt to connect to the Internet.
- InternetAutoDial() forces the modem to automatically dial when a connection to the Internet is made.
- InternetAutoDialHangup() disconnects an Automatic-dialup session.
- InternetCanonicalizeUrl() canonicalizes the URL.
- InternetCloseHandle() closes an internet handle.
- InternetCombineUrl() combines a base and a relative URL to a single URL.
- InternetConnect() connects to the Internet, opening an FTP, HTTP session, or Gopher session.
- InternetCrackUrl() cracks a URL into the component parts.
- InternetCreateUrl() creates a URL from the component parts.
- InternetDial() utilizes a modem to create an Internet connection.
- InternetErrorDlg() displays a dialog box for Internet errors.
- InternetFindNextFile() continues a file search on an FTP site or Gopher site.
- InternetGetConnectedState() returns the connected state.
- InternetGetCookie() gets a cookie from a specified URL.
- InternetGetLastResponseInfo() gets the last Internet function error description.
- InternetGoOnline() prompts the user before connecting to a URL, thus getting permission.
- InternetHangup() forces the modem to hang up.
- InternetLockRequestFile() allows the user to lock a file that is being used.
- InternetInitializeAutoProxyDLL() is not supported.
- InternetOpen() initializes an application to use the Internet functions.
- InternetOpenUrl() begins reading a complete HTTP, FTP, or Gopher URL.
- InternetQueryDataAvailable() sends a query to the server to determine how much data is currently available.
- InternetQueryOption() queries an Internet option on the specified handle.
- InternetReadFile() reads data from an opened handle.
- InternetSetCookie() creates a cookie from the specified URL.
- InternetSetFilePointer() sets a file position for InternetReadFile().
- InternetSetOption() sets an Internet option.
- InternetSetOptionEx() is not currently implemented.
- InternetSetStatusCallback() sets up a callback function.
- InternetTimeFromSystemTime() formats a date and time based on the HTTP version 1.0 specification.
- InternetTimeToSystemTime() converts an HTTP time/date string to a SYSTEMTIME structure.
- InternetUnlockRequestFile() unlocks a locked file
- InternetWriteFile() writes data to an Internet file that is open.
- ReadUrlCacheEntryStream() reads cached data from a stream opened with RetrieveUrlCacheEntryStream().
- RetrieveUrlCacheEntryFile() retrieves cache data as a file.
- RetrieveUrlCacheEntryStream() opens a stream for data from the cache.
- SetUrlCacheConfigInfo() sets cache configuration information.
- SetUrlCacheEntryGroup() sets information in a cache group.
- SetUrlCacheEntryInfo() sets information in a cache entry.
- UnlockUrlCacheEntryFile() unlocks a cache file locked with RetrieveUrlCacheEntryFile().
- UnlockUrlCacheEntryStream() releases a stream locked by RetreiveUrlCacheEntryStream().
Gopher Client Functions | Next Section

Account Sign In
View your cart