ISAPI Server Extensions

An ISAPI server extension is a program (implemented as a DLL loaded by IIS) that runs in response to a GET or POST request from a client program (browser). The browser can pass parameters to the program, which are often values that the browser user types into edit controls, selects from list boxes, and so forth. The ISAPI server extension typically sends back HTML code based on those parameter values. You'll better understand this process when you see an example.

Common Gateway Interface and ISAPI

Internet server programs were first developed for UNIX computers, so the standards were in place long before Microsoft introduced IIS. The Common Gateway Interface (CGI) standard, actually part of HTTP, evolved as a way for browser programs to interact with scripts or separate executable programs running on the server. Without altering the HTTP/CGI specifications, Microsoft designed IIS to allow any browser to load and run a server DLL. DLLs are part of the IIS process and thus are faster than scripts that might need to load separate executable programs. Because of your experience, you'll probably find it easier to write an ISAPI DLL in C++ than to write a script in PERL, the standard Web scripting language for servers.

CGI shifts the programming burden to the server. Using CGI parameters, the browser sends small amounts of information to the server computer, and the server can do absolutely anything with this information, including access a database, generate images, and control peripheral devices. The server sends a file (HTML or otherwise) back to the browser. The file can be read from the server's disk, or it can be generated by the program. No ActiveX controls or Java applets are necessary, and the browser can be running on any type of computer.

A Simple ISAPI Server Extension GET Request

Suppose an HTML file contains the following tag:

<a href="scripts/maps.dll?State=Idaho">Idaho Weather Map</a><p>

When the user clicks on Idaho Weather Map, the browser sends the server a CGI GET request like this:

GET scripts/maps.dll?State=Idaho HTTP/1.0

IIS then loads maps.dll from its scripts (virtual) directory, calls a default function (often named Default), and passes it the State parameter Idaho. The DLL then goes to work generating a JPG file containing the up-to-the-minute satellite weather map for Idaho and sends it to the client.

If maps.dll had more than one function, the tag could specify the function name like this:

<a href="scripts/maps.dll?GetMap?State=Idah o&Res=5">Idaho Weather Map</a><p>

In this case, the function GetMap is called with two parameters, State and Res.

You'll soon learn how to write an ISAPI server similar to maps.dll, but first you'll need to understand HTML forms, because you don't often see CGI GET requests by themselves.

HTML Forms—GET vs. POST

In the HTML code for the simple CGI GET request above, the state name was hard-coded in the tag. Why not let the user select the state from a drop-down list? For that, you need a form, and here's a simple one that can do the job.

<html> <head><title>Weathermap HTML Form</title> </head> <body> <h1><center>Welcome to the Satellite Weathermap Service</center></h1> <form action="scripts/maps.dll?GetMap" method=GET>     <p>Select your state:     <select name="State">         <option> Alabama         <option> Alaska         <option> Idaho         <option> Washington     </select> <p><input type="submit"><input type="reset"> </form> </body></html>

If you looked at this HTML file with a browser, you would see the form shown in Figure 35-4.

click to view at full size.

Figure 35-4. The Weathermap HTML Form window.

The select tag provides the state name from a list of four states, and the all-important "submit" input tag displays the pushbutton that sends the form data to the server in the form of a CGI GET request that looks like this:

GET scripts/maps.dll?GetMap?State=Idaho HTTP/1.0 (various request headers) (blank line)

Unfortunately, some early versions of the Netscape browser omit the function name in form-originated GET requests, giving you two choices: provide only a default function in your ISAPI DLL, and use the POST method inside a form instead of the GET method.

If you want to use the POST option, change one HTML line in the form above to the following:

<form action="scripts/maps.dll?GetMap" method=POST>

Now here's what the browser sends to the server:

POST scripts/maps.dll?GetMap (various request headers) (blank line) State=Idaho

Note that the parameter value is in the last line instead of in the request line.

ISAPI DLLs are usually stored in a separate virtual directory on the server because these DLLs must have execute permission but do not need read permission. Clicking the Edit Properties button shown in Figure 35-3 will allow you to access these permissions from the Internet Service Manager, or you can double-click on a directory to change its properties.

Writing an ISAPI Server Extension DLL

Visual C++ gives you a quick start for writing ISAPI server extensions. Just select ISAPI Extension Wizard from the Projects list. After you click the OK button, your first screen looks like Figure 35-5.

click to view at full size.

Figure 35-5. The Step 1 page of the ISAPI Extension Wizard.

Check the Generate A Server Extension Object box, and you've got a do-nothing DLL project with a class derived from the MFC CHttpServer class and a Default member function. Now it's time for a little programming.

You must write your ISAPI functions as members of the derived CHttpServer class, and you must write parse map macros to link them to IIS. There's no "parse map wizard," so you have to do some coding. It's okay to use the Default function, but you need a GetMap function too. First insert these lines into the wizard-generated parse map:

ON_PARSE_COMMAND(GetMap, CWeatherExtension, ITS_PSTR) ON_PARSE_COMMAND_PARAMS("State")

Then write the GetMap function:

void CWeatherExtension::GetMap(CHttpServerContext* pCtxt, LPCTSTR pstrState) {     StartContent(pCtxt);     WriteTitle(pCtxt);     *pCtxt << "Visualize a weather map for the state of ";     *pCtxt << pstrState;     EndContent(pCtxt); }

This function doesn't actually generate the weather map (what did you expect?), but it does display the selected state name in a custom HTML file. The CHttpServer::StartContent and CHttpServer::EndContent functions write the HTML boilerplate, and CHttpServer::WriteTitle calls the virtual CHttpServer::GetTitle function, which you need to override:

LPCTSTR CWeatherExtension::GetTitle() const {     return "Your custom weather map"; // for browser's title window }

The MFC CHttpServerContext class has an overloaded << operator, which you use to put text in the HTML file you're building. Behind the scenes, an attached object of the MFC class CHtmlStream represents the output to the server's socket.

The MFC ISAPI Server Extension Classes

Now is a good time to review the three MFC classes that are used to create an MFC ISAPI server extension. Remember that these classes are for ISAPI server extensions only. Don't even think of using them in ordinary Winsock or WinInet applications.

CHttpServer

With the help of the ISAPI Extension Wizard, you derive a class from CHttpServer for each ISAPI server extension DLL that you create. You need one member function for each extension function (including the default function), and you need an overridden GetTitle function. The framework calls your extension functions in response to client requests, using the connections established in the parse map. The ISAPI Extension Wizard provides an overridden GetExtensionVersion function, which you seldom edit unless you need initialization code to be executed when the DLL is loaded.

One of the CHttpServer member functions that you're likely to call is AddHeader, which adds special response headers, such as Set-Cookie, before the response is sent to the server. (More on cookies later.)

CHttpServerContext

There's one CHttpServer object per DLL, but there is one CHttpServerContext object for each server transaction request. Your extension functions each provide a pointer to one of these objects. You don't derive from CHttpServerContext, so you can't easily have variables for individual transactions. Because different IIS threads can manage transactions, you have to be careful to perform synchronization for any data members of your CHttpServer class or global variables.

You've already seen the use of the StartContent, EndContent, and WriteTitle functions of the CHttpServer class plus the overloaded >> operator. You might also need to call the CHttpServerContext::GetServerVariable function to read information sent by the client in the request headers.

CHtmlStream

Most of the time, you don't use the CHtmlStream class directly. The CHttpServerContext class has a CHtmlStream data member, m_pStream, that's hooked up to the >> operator and serves as the output for HTML data. You could access the CHtmlStream object and call its Write member function if you needed to send binary data to the client. Because objects of the CHtmlStream class accumulate bytes in memory before sending them to the client, you need an alternative approach if your DLL relays large files directly from disk.



Programming Visual C++
Advanced 3ds max 5 Modeling & Animating
ISBN: 1572318570
EAN: 2147483647
Year: 1997
Pages: 331
Authors: Boris Kulagin

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