A Simple HTTP Client


In this section we describe the steps you need to take when you develop a basic HTTP client application. To start, a simple call to the Navigate method of the CAtlHttpClient class will send an HTTP request to the specified URL:

 CAtlHttpClient client;  if( client.Navigate( "http://localhost/HTTPClient/test.html" ) )      printf( "Return Code -- %d\n", client.GetStatus() ); 

Most likely, this code will display something like this:

 Return Code -- 200 

with 200 being the HTTP code for success.

In this section, we incrementally analyze how you can build the URL parameter from components , how you can customize the HTTP request to use a different HTTP verb ( POST , for instance, instead of the default GET verb), and how you can retrieve the whole HTTP response (not only the status code). You can perform all these operations with the different overloads of the Navigate method.

There are three overloads for the Navigate method:

 bool Navigate(     LPCTSTR szURL,     ATL_NAVIGATE_DATA * pNavData = NULL  ) throw(...);  bool Navigate(     LPCTSTR szServer,     LPCTSTR szPath,     ATL_NAVIGATE_DATA * pNavData = NULL  ) throw(...);  bool Navigate(     const CUrl* pUrl,     ATL_NAVIGATE_DATA * pNavData = NULL  ) throw(...); 

In all of the overloads, the pNavData parameter has the same meaning, which we discuss later.

The first overload (the one used in the code snippet) works fine when the URL to receive the request is simple enough to be hard-coded inside the application or entered as a parameter ( user input).

This isn t the case for most applications. Assuming that the path to the object is constant (something that isn t very common), at least the server name should be entered as a parameter (so that the HTTP call can be easily routed to a different server). The second overload is helpful for this scenario ”it allows separation between the server name and the server path to the request object.

You can assemble components of more complex URLs in strings to use in either of these overloads. However, the task of merging strings (such as username, password, local object paths, and query parameters) and numbers (such as the port number) into a URL that s compliant with the HTTP specification can prove time-consuming and bug-prone. Fortunately, ATL Server provides a class, CUrl , that does most of this work for you. CUrl provides methods to separately access and modify components of a URL and also to get a complete URL string built from those components.

For instance, you can build a rather complex URL like the following:

 https://someone:secret@www.microsoft.com:8080/visualc/stuff.htm#contents 

using a CUrl object in a few calls as follows :

 CUrl    url;      url.SetScheme(ATL_URL_SCHEME_HTTPS);      url.SetUserName("someone");      url.SetPassword("secret");      url.SetHostName("www.microsoft.com");      url.SetPortNumber(8080);      url.SetUrlPath("/visualc/stuff.htm");      url.SetExtra("#contents"); 

This code should be easier to maintain. Also, by separating all the URL components, this code allows for tighter validation of each field (e.g., with regular expressions).

Note  

CUrl isn t the main subject of this section. However, we should note that it supports generating a full URL string out of the components, with a few different escaping schemes that make it compatible with older WinINet code ( InternetCreateUrl ). It also supports the reverse operation, (i.e., parsing an existing URL string and separating the various components of the string), via the CrackUrl method, the equivalent of the WinINet InternetCrackUrl API.

The third overload of the CAtlHttpClient::Navigate method takes as a parameter a pointer to a CUrl object.

Let s look now at the last parameter in all three overloads: the ATL_NAVIGATE_DATA structure pointer. This structure contains information about the HTTP request to be sent. The various fields of an HTTP request appear as fields of the structure. The structure members can be classified as follows:

  • Request content (such as data to be posted or additional HTTP headers)

  • Helpers for sending content (such as the packet size for the request or callbacks for streaming data to the server)

  • Helpers for receiving content (such as the packet size for reading the response or callbacks for data streamed by the server, or the maximum time to wait for a response)

  • Behavioral flags that describe the actions to be performed by the HTTP client for specific server response codes (such as automatically handling redirections)

By manipulating the members of this structure, you have full control over the behavior of the HTTP client.

The behavior modification flags prove extremely useful in making the HTTP client as easy to use as a browser (with automatic redirection or authentication and no concern for the response content until it s downloaded) or as flexible as a detailed set of Internet APIs. Furthermore, a class provided in ATL Server, CAtlNavigateData , encapsulates the ATL_NAVIGATE_DATA structure and provides public methods for accessing and modifying these fields. The next sections provide more detail on how you can use the CAtlNavigateData structure.

The invocation of one of the Navigate methods will return a boolean true if the request is sent and any response comes from the server.

When true is returned from the Navigate method, it means that the request was completed successfully and the server returned a success code. However, false may have multiple meanings. Therefore, you can make a complete conclusion on the status of the request only after you inspect both the result of Navigate and the result of GetStatus . For the Visual Studio .NET release of ATL Server, Table 25-1 describes the possible states. However, this may change in later releases and service packs .

Table 25-1. The Meaning of Different Status Values After a Failing Navigate Call

NAVIGATE

GETSTATUS

MEANING

false

ATL_INVALID_STATUS (< 0)

No valid response (can t connect to the server, timeout occurred, there was an error parsing the response, and so forth).

false

301 “303

Autoredirect is disabled or it failed.

false

401, 407

Negotiate authentication failed.

true

200 “206, 304, or 305

SUCCESS (and the respective HTTP meaning).

false

Any code not mentioned previously

ERROR (the specific HTTP meaning of that code. For instance, 500 is Internal Server Error).

If the status is greater than 0, the error message that comes from the server can be retrieved in the same way as the regular HTTP response content.

Once you ve invoked Navigate , if some response is available, you can obtain it by using GetResponseLength and GetResponse , two methods offered by the HTTP client class.

The code snippet at the beginning of this section, when modified to display the response, looks like this:

 CAtlHttpClient client;  client.Navigate( "http://localhost/HTTPClient/test.html" );  if (client.GetStatus() != ATL_INVALID_STATUS)  {      // Display any response, not only for success      DWORD    dwResponseLength = client.GetResponseLength();      const BYTE*    pResponse = client.GetResponse();      char*    pText = new char[dwResponseLength+1];      // ensure the trailing zero for printf      memcpy( pText, pResponse, dwResponseLength);      pText[dwResponseLength] = 0;      printf("\n\n%s\n\n", pText);  } 

The output looks like this:

 HTTP/1.1 200 OK  Server: Microsoft-IIS/5.1  Date: Wed, 13 Nov 2002 10:03:31 GMT  Content-Type: text/html  Accept-Ranges: bytes  Last-Modified: Sun, 20 Oct 2002 18:39:03 GMT  ETag: "708e89f66778c21:8ca"  Content-Length: 54  <html>  <body>          This is a Test Page  </body>  </html> 

As you can see, the response contains all the HTTP incoming traffic (including status code, headers, and so forth). If some HTTP 100 Continue responses are issued before the actual content, these are going to be displayed too. This might prove useful in debugging an application or in handling some HTTP error code. But, for a successful request, usually only the actual body of the response matters (in the preceding output, the text between < html > and < /html > ). To get the filtered body of the response, simply replace GetResponseLength() and GetResponse() with GetBodyLength() and GetBody() , respectively, in the preceding code snippet.

We ve discussed so far the main code path for sending an HTTP request and retrieving the response with the ATL Server HTTP client classes. The code snippets presented so far should provide enough information for you to create simple applications and expect success in most cases. Please consult the MSDN documentation for up-to-date details on all the methods of CUrl , CAtlNavigateData , and the other classes discussed here.

The next section covers sending and receiving complex data, such as multiple form/query parameters or chunked content.




ATL Server. High Performance C++ on. NET
Observing the User Experience: A Practitioners Guide to User Research
ISBN: B006Z372QQ
EAN: 2147483647
Year: 2002
Pages: 181

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net