More Complex HTTP Requests Using a Session

The simple HTTP request described in previous sections allows resources to be downloaded. However, you will need more control when sending data to the server or making more complex requests. For example, you may want to specify usernames and passwords. This section describes how to open a request, to send headers, and to send data to the server.

The following calls are required in order to make HTTP requests:

  1. InternetOpen to initialize the Windows CE Internet functions and return a handle to access other Internet functions

  2. InternetConnect to make a connection to the Internet server and return a connection, or session, handle

  3. HttpOpenRequest to specify the URL (Universal Resource Locator) of the resource to be acquired (for example, the HTML page) and return a request handle

  4. HttpSendRequest to send the request specified in HttpOpenRequest to the server

  5. InternetReadFile repeatedly until all the data has been read from the server

  6. InternetCloseHandle on each handle returned from steps 1-3

Certain steps in the above list can be repeated. For example, if you want to request multiple HTML files from the same server, you can repeat steps 3 and 4 as required. You need only call step 1 once when the application starts, and step 6 for the handle returned from InternetOpen when the application terminates (Figure 8.2).

Figure 8.2. Function-calling sequence for Internet and HTTP functions


Cracking the URL—InternetCrackUrl

Each resource on the Internet or on an intranet has a unique name called a Universal Resource Locator, or URL. The URL contains information such as the following:

  1. The protocol used to access the URL (such as HTTP).

  2. The server the resource is located on, either as a named server (for example, www.microsoft.com) or an IP address (192.168.0.2).

  3. The resource name's location on the server. This is typically a folder or directory specification including the name of the file.

  4. The port number used on the server for the protocol being specified. Most protocols usually have a default port number (HTTP is 80), but this may be different on some servers.

A fully qualified URL, including a port number and fully qualified resource name, looks like "http://www.microsoft.com:80/windowsce/default.asp," which can be shortened using defaults to http://www.microsoft.com/windowsce/, since 80 is the default port number and default.asp is the default resource name for this site.

When you receive a URL from the user, you need to be able to parse out the server name and resource name, and this can become quite complex. Fortunately, Windows CE provides the InternetCrackUrl function for doing this (Table 8.5).

Table 8.5. InternetCrackURL—Breaks a URL into components
InternetCrackURL 
LPCTSTR lpszUrlPointer to the URL to be parsed
DWORD dwUrlLengthLength of the URL, or zero if NULL-terminated
DWORD dwFlagsSet to 0 to parse URL without encoding or decoding characters
LPURL_COMPONENTS lpUrlComponentsURL_COMPONENTS structure into which the parsed URL elements are returned
BOOL Return ValueTRUE for success, FALSE for failure

The trick to using this function successfully is the initialization of the URL_COMPONENTS structure. This structure contains pointers to the various possible elements of the URL. These pointers must either be initialized to NULL if the element is not to be returned, or point at a string buffer if it is to be returned. In the following code fragment a URL_COMPONENT structure is initialized to return the server name and the path to the resource. Further, the dwStructSize member must be initialized to the size of the structure.

URL_COMPONENTS crackedURL;
TCHAR szServer[1024];
TCHAR szPath[1024];
memset(&crackedURL, 0, sizeof(crackedURL));
crackedURL.dwStructSize = sizeof(crackedURL);
crackedURL.lpszHostName = szServer;
crackedURL.dwHostNameLength = 1024;
crackedURL.lpszUrlPath = szPath;
crackedURL.dwUrlPathLength = 1024;
InternetCrackUrl(szURL, 0, 0, &crackedURL);

In this code fragment, the string szURL contains the full URL (for example, http://www.microsoft.com/windowsce/default.asp. On return lpszHostName would contain www.microsoft.com and lpszURLPath would contain "/windowsce/default.asp".

Connecting to a Server—InternetConnect

The function InternetConnect (Table 8.6) is used to make a connection to a specified server, and is passed access information (for example, the user-name and password to connect with) and the port number and protocol to use. Once a connection has been made, multiple requests can be made to retrieve resources.

Table 8.6. InternetConnect—Connects to a server
InternetConnect 
HINTERNET hInternetHandle returned from InternetOpen
LPCTSTR lpszServerNameServer name, e.g. "www.microsoft.com"
INTERNET_PORT nServerPortPort number, e.g. INTERNET_DEFAULT_HTTP_PORT for HTTP
LPCTSTR lpszUserNamePointer to the user name used to validate access to the server, or NULL for anonymous login
LPCTSTR lpszPasswordPointer to the password, or NULL for anonymous login
DWORD dwServiceService or protocol to use, e.g. INTERNET_SERVICE_HTTP
DWORD dwFlagsFlags specifying options, or 0 for no options
DWORD dwContextContext value used in callback functions
HANDLE Return ValueSession handle, or NULL if function call fails

Most servers on the Internet do not require valid usernames and passwords—they use anonymous login. In this situation, the call to InternetConnect is straightforward. In the following code fragment, a connection is made to the server name returned from cracking a fully qualified URL using the HTTP protocol.

HINTERNET hHttpSession = NULL;
hHttpSession = InternetConnect(hHttpOpen,
  crackedURL.lpszHostName,    // server name
  INTERNET_DEFAULT_HTTP_PORT,
  NULL     // username
  NULL,    // password
  INTERNET_SERVICE_HTTP,
  0,   // no flags
  0); // no context

There are a number of issues to consider when connecting to a secure Internet site, and these are covered later in the chapter.

Obtaining a Request Handle—HttpOpenRequest

All the functions used so far are generic Internet functions—they are used for HTTP, FTP, and any other supported protocols. The function HttpOpenRequest (Table 8.7) is, as its name implies, specific to the HTTP protocol and is used to open a handle through which a request to download a resource (such as a file or image) is made.

Simple requests generally use the GET verb. Small amounts of information can be sent to the server in the URL. The POST verb is used for sending larger amounts of data (such as files) to the server. These topics are covered later in this chapter.

Table 8.7. HttpOpenRequest—Opens a request handle
HttpOpenRequest 
HINTERNET hHttpSessionHandle returned from InternetConnect.
LPCTSTR lpszVerbHTTP verb, usually either "GET" or "POST". NULL specifies "GET".
LPCTSTR lpszObjectNameResource path and name obtained from Internet-CrackUrl.
LPCTSTR lpszVersionHTTP version to use, or NULL for the default "HTTP/1.0".
LPCTSTR lpszReferrerURL of the document from which a hypertext jump was made to this resource. NULL for no referrer.
LPCTSTR *lplpszAcceptTypesTypes of documents that the client can accept. NULL implies only "text/*" documents.
DWORD dwFlagsOptions for connection semantics, etc. 0 for no options. Most Windows NT options are not supported in Windows CE.
DWORD dwContextContext value used in callback functions.
HANDLE Return ValueRequest handle, or NULL on failure.

The next code fragment shows how to make a simple request to an HTTP server using the resource path obtained through calling InternetCrackUrl.

hHttpRequest = HttpOpenRequest(hHttpSession,
  NULL,    // verb is 'GET'
  crackedURL.lpszUrlPath,
  NULL,    // default version
  NULL,    // no referrer
  NULL,    // only accept text/* files
  0,    // no flags
  0);   // no context for call backs

Making the Request—HttpSendRequest

After opening a request using HttpOpenRequest, the function HttpSendRequest (Table 8.8) is called to send the request off to the server:

HttpSendRequest(hHttpRequest,
  NULL, 0,          // no headers
  0, 0));        // no optional data

Additional HTTP headers can be specified when the request is sent by calling HttpSendRequest. Alternatively, additional headers can be added using the function HttpAddRequestHeaders before the request is sent. This is illustrated later in the chapter.

Table 8.8. HttpSendRequest—Sends a request to the server
HttpSendRequest 
HINTERNET hRequestRequest handle obtained from HttpOpenRequest
LPCTSTR lpszHeadersAdditional headers, or NULL for none
DWORD dwHeadersLengthLength of additional headers, or 0 for none
LPVOID lpOptionalOptional data, or NULL for none
DWORD dwOptionalLengthLength of optional data, or 0 for none
BOOL Return ValueTRUE on success, otherwise FALSE

Listing 8.2 shows the entire code used to prompt the user for a URL and display the HTML code returned from the server.

Listing 8.2. Making an HTTP request using a session
#define CHUNKSIZE 500
void Listing8_2()
{
  TCHAR szURL[MAX_PATH + 1];
  HINTERNET hHttpOpen = NULL;
  HINTERNET hHttpSession = NULL;
  HINTERNET hHttpRequest = NULL;
  char charBuffer[CHUNKSIZE + 1];
  TCHAR szBuffer[CHUNKSIZE + 1];
  DWORD dwRead;
  URL_COMPONENTS crackedURL;
  TCHAR szServer[1024];
  TCHAR szPath[1024];
  if(!GetTextResponse(_T("Enter URL to Display: "),
        szURL, MAX_PATH))
     return;
 
  hHttpOpen = InternetOpen(
       _T("Example Agent"),
       INTERNET_OPEN_TYPE_DIRECT,
       NULL, // no proxy
       NULL, // no bypass addresses
       0); // no flags
  if(hHttpOpen == NULL)
  {
    cout ≪ _T("Could not open internet session ")
         ≪ GetLastError();
    goto cleanUp;
  }
  // Crack the URL to get the server name
  memset(&crackedURL, 0, sizeof(crackedURL));
  crackedURL.dwStructSize = sizeof(crackedURL);
  crackedURL.lpszHostName = szServer;
  crackedURL.dwHostNameLength = 1024;
  crackedURL.lpszUrlPath = szPath;
  crackedURL.dwUrlPathLength = 1024;
  if(!InternetCrackUrl(szURL, 0, 0, &crackedURL))
  {
     cout ≪ _T("Cannot crack URL") ≪ GetLastError();
     goto cleanUp;
  }
  hHttpSession = InternetConnect(hHttpOpen,
     crackedURL.lpszHostName, // server name
     INTERNET_DEFAULT_HTTP_PORT,
     NULL,           // username
     NULL,           // password
     INTERNET_SERVICE_HTTP,
     0, // no flags
     0); // no context
  if(hHttpSession == NULL)
  {
    cout ≪ _T("Could not open Internet connection")
         ≪ GetLastError();
    goto cleanUp;
  }
  hHttpRequest = HttpOpenRequest(hHttpSession,
       NULL,           // verb is 'GET'
       crackedURL.lpszUrlPath,
       NULL,           // default version
       NULL,           // no referrer
       NULL,           // only accept text/* files
       0,      // no flags
       0);     // no context for call backs
  if(hHttpRequest == NULL)
  {
    cout ≪ _T("Could not get HTTP request ")
         ≪ GetLastError();
    goto cleanUp;
  }
  if(!HttpSendRequest(hHttpRequest,
     NULL, 0,            // no headers
     0, 0))     // no optional data
  {
    cout ≪ _T("Could not read data ")
         ≪ GetLastError();
    goto cleanUp;
  }
  do
  {
     // read from Internet HTTP server
     if(!InternetReadFile(hHttpRequest, charBuffer,
           CHUNKSIZE, &dwRead))
     {
       cout ≪ _T("Could not send request")
           ≪ GetLastError();
       goto cleanUp;
     }
     // convert to Unicode and display
     charBuffer[dwRead] = '';
     mbstowcs(szBuffer, charBuffer, dwRead);
     szBuffer[dwRead] = '';
     cout ≪ szBuffer;
  } while(dwRead > 0);
cleanUp:
  if(hHttpRequest != NULL)
     InternetCloseHandle(hHttpRequest);
  if(hHttpSession != NULL)
     InternetCloseHandle(hHttpSession);
  if(hHttpOpen != NULL)
     InternetCloseHandle(hHttpOpen);
}

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.216.190.167