Sun Java System Web Server 7.0 Update 3 NSAPI Developer's Guide

Chapter 4 Examples of Custom SAFs and Filters

This chapter provides examples of custom Sever Application Functions (SAFs) and filters for each directive in the request-response process. You can use these examples as the basis for implementing your own custom SAFs and filters. For more information about creating your own custom SAFs, see Chapter 2, Creating Custom Server Application Functions. For information about creating your own filters, see Chapter 3, Creating Custom Filters.

Before writing your own SAF, check to see whether an existing SAF serves your purpose. The predefined SAFs are discussed in the Sun Java System Web Server 7.0 Update 3 Administrator’s Configuration File Reference.

If you need to writer a custom SAF, you should be familiar with the request-response process and the role of the configuration file obj.conf. See the Sun Java System Web Server 7.0 Update 3 Administrator’s Configuration File Reference for information on the obj.conf file.

For a list of the NSAPI functions for creating new SAFs, see Chapter 6, NSAPI Function and Macro Reference.

This chapter has the following sections:

Using the NSAPI Examples

The install-dir/samples/nsapi directory contains examples of source code for SAFs.

You can use the example.mak (Windows) or Makefile (UNIX) makefile in the same directory to compile the examples and create shared libraries containing the functions in all of the example files.

To test an example, load the examples shared library into the server by adding the following directive in the Init section of magnus.conf:


Init fn=load-modules 
     shlib=examples.so/dll
     funcs=function1,...,functionN

      

The shlib parameter specifies the path to the shared library, for example, ../../samples/nsapi/examples.so, and the funcs parameter specifies the functions to load from the shared library.

If the example uses an initialization function, be sure to specify the initialization function in the funcs argument to load-modules. Also, add an Init directive to call the initialization function.

For example, the PathCheck example implements the restrict-by-acf function, which is initialized by the acf-init function. The following directive loads both these functions:

Init fn=load-modules
     shlib="path"  
     funcs=acf-init,restrict-by-acf

The following directive calls the acf-init function during server initialization:

Init fn=acf-init file=extra-arg

To invoke the new SAF at the appropriate step in the response handling process, add an appropriate directive in the object to which it applies, for example:

PathCheck fn=restrict-by-acf

After adding new Init directives to magnus.conf, restart the Web Server to load the changes. Init directives are only applied during server initialization.

AuthTrans() Example

This simple example of an AuthTrans function demonstrates how to use your own custom methods to verify that the user name and password that a remote client provides is accurate. This program uses a hard-coded table of user names and passwords and checks a given user's password against the one in the static data array. The userdb parameter is not used in this function.

AuthTrans directives work in conjunction with PathCheck directives. Generally, an AuthTrans function checks whether the user name and password associated with the request are acceptable. However, it does not allow or deny access to the request. The PathCheck function handles access.

AuthTrans functions get the user name and password from the headers associated with the request. When a client initially makes a request, the user name and password are unknown. The AuthTrans function and PathCheck function reject the request, because the user name and password have not yet been submitted. When the client receives the rejection, the usual response is to present a dialog box asking the user for their user name and password. The client then submits the request again, this time including the user name and password in the headers.

In this example, the hardcoded-auth function, which is invoked during the AuthTrans step, checks whether the user name and password correspond to an entry in the hard-coded table of users and passwords.

Installing the AuthTrans() Example

To install the function on the Web Server, add the following Init directive to magnus.conf to load the compiled function:

Init fn=load-modules 
     shlib="path" 
     funcs=hardcoded-auth

Inside the default object in obj.conf, add the following AuthTrans directive:


AuthTrans fn=basic-auth 
          auth-type="basic" 
          userfn=hardcoded-auth
          userdb=unused

         

Note that this function does not actually enforce authorization requirements. It only takes given information and tells the server whether it is correct. The PathCheck function require-auth performs the enforcement. Therefore, add the following PathCheck directive:

PathCheck fn=require-auth 
          realm="test realm" 
          auth-type="basic"

The source code for this example is in the auth.c file in the install-dir/samples/nsapi/directory.

NameTrans() Example

The ntrans.c file in the samples/nsapi subdirectory of the server root directory contains source code for two example NameTrans functions:

This section discusses the first example. The second example is found in ntrans.c.


Note –

A NameTrans function is used primarily to convert the logical URL in ppath in rq->vars to a physical path name. However, the example discussed here, explicit_pathinfo, does not translate the URL into a physical path name. It changes the value of the requested URL. See the second example, https_redirect, in ntrans.c for an example of a NameTrans function that converts the value of ppath in rq->vars from a URL to a physical path name.


The explicit_pathinfo example enables URLs to explicitly include extra path information for use by a CGI program. The extra path information is delimited from the main URL by a specified separator, such as a comma. For example:

http://server-name/cgi/marketing,/jan/releases/hardware

In this case, the URL of the requested resource, a CGI program is http://server-name/cgi/marketing. The extra path information to give to the CGI program is /jan/releases/hardware.

When choosing a separator, be sure to pick a character that is never used as part of a real URL.

The explicit_pathinfo function reads the URL, strips out everything following the comma, and puts the string in the path-info field of the vars field in the request object (rq->vars). CGI programs can access this information through the PATH_INFO environment variable.

One side effect of explicit_pathinfo is that the SCRIPT_NAME CGI environment variable has the separator character appended to the end.

NameTrans directives usually return REQ_PROCEED when they change the path, so that the server does not process any more NameTrans directives. However, in this case name translation needs to continue after the path info is extracted, because the URL to a physical path name has not yet been translated.

Installing the NameTrans Example

To install the function on the Web Server, add the following Init directive to magnus.conf to load the compiled function:

Init fn=load-modules 
     shlib="path" 
     funcs=explicit-pathinfo

Inside the default object in obj.conf, add the following NameTrans directive:

NameTrans fn=explicit-pathinfo 
          separator=","

This NameTrans directive should appear before other NameTrans directives in the default object.

The source code for this example is in the ntrans.c file in the install-dir/smaples/nsapi/directory.

PathCheck() Example

The example in this section demonstrates how to implement a custom SAF for performing path checks. This example simply checks whether the requesting host is on a list of allowed hosts.

The Init function acf-init loads a file containing a list of allowable IP addresses with one IP address per line. The PathCheck function restrict_by_acf gets the IP address of the host that is making the request and checks whether it is on the list. If the host is on the list, it is allowed access. Otherwise, access is denied.

For simplicity, the stdio library is used to scan the IP addresses from the file.

Installing the PathCheck() Example

To load the shared object containing your functions, add the following directive in the Init section of the magnus.conf file:

Init fn=load-modules 
     shlib="path"
     funcs=acf-init, restrict-by-acf

To call acf-init to read the list of allowable hosts, add the following line to the Init section in magnus.conf. This line must come after the one that loads the library containing acf-init.

Init fn=acf-init 
     file=fileContainingHostsList

To execute your custom SAF during the request-response process for some object, add the following line to that object in the obj.conf file:

PathCheck fn=restrict-by-acf

The source code for this example is in pcheck.c in the install-dir/samples/nsapi/directory.

ObjectType() Example

The example in this section demonstrates how to implement html2shtml, a custom SAF that instructs the server to treat a .html file as a .shtml file if a .shtml version of the requested file exists.

A well-behaved ObjectType function checks whether the content type is already set. If the type is set, the function returns REQ_NOACTION.


if(pblock_findval("content-type", rq->srvhdrs))
    return REQ_NOACTION;

      

If the content type is not set, ObjectType directive sets the content type. This example sets the content type to magnus-internal/parsed-html in the following lines:


/* Set the content-type to magnus-internal/parsed-html */
pblock_nvinsert("content-type", "magnus-internal/parsed-html",
                rq->srvhdrs);

      

The html2shtml function checks the requested file name. If the name ends with .html, the function searches for a file with the same base name, with the extension .shtml. If a .shtml is found, the function uses that path and informs the server that the file is parsed HTML instead of regular HTML. Note that this check requires an extra stat call for every HTML file accessed.

Installing the ObjectType() Example

To load the shared object containing your function, add the following directive in the Init section of the magnus.conf file:

Init fn=load-modules
     shlib="path" 
     funcs=html2shtml

To execute the custom SAF during the request-response process for an object, add the following code to that object in the obj.conf file:

ObjectType fn=html2shtml

The source code for this example is in otype.c in the install-dir/samples/nsapi/ directory.

Output() Example

This section describes an example NSAPI filter named example-replace, which examines outgoing data and substitutes one string for another. This example shows how to create a filter that intercepts and modifies outgoing data.

Installing the Output() Example

To load the filter, add the following directive in the Init section of the magnus.conf file:


Init fn="load-modules" 
     shlib=yourlibrary
     NativeThread="no"

To execute the filter during the request-response process for an object, add the following code to that object in the obj.conf file:


Output fn="insert-filter" 
       type="text/*" 
       filter="example-replace" 
       from="iPlanet" to="Sun ONE"
        

The source code for this example is in the replace.c file in the install-dir/samples/nsapi/ directory.

Service() Example

This section discusses two Service() function examples: one simple and one more complex.

Simple Service() Example

This section describes a very simple Service function called simple_service. This function sends a message in response to a client request. The message is initialized by the init_simple_service function during server initialization.

To load the shared object containing your functions, add the following directive in the Init section of the magnus.conf file:


Init fn=load-modules 
     shlib=yourlibrary 
     funcs=simple-service-init,simple-service

         

To call the simple-service-init function to initialize the message representing the generated output, add the following directive to the Init section in magnus.conf. This directive must come after the directive that loads the library containing simple-service-init.


Init fn=simple-service-init
     generated-output="<H1>Generated-output-msg</H1>"

         

To execute the custom SAF during the request-response process for an object, add the following code to that object in the obj.conf file:

Service type="text/html" 
        fn=simple-service

The type="text/html" argument indicates that this function is invoked during the Service stage only if the content-type has been set to text/html.

The source code for this example is in the service.c file in the install-dir/samples/nsapi directory.

More Complex Service() Example

The send-images function is a custom SAF that replaces the doit.cgi demonstration available on the iPlanet home pages. When a file is accessed as /dir1/dir2/something.picgroup, the send-images function checks whether the file is being accessed by a Mozilla 1.1 browser. If not, the function sends a short error message. The file something.picgroup contains a list of lines, each of which specifies a file name followed by a content-type. For example, one.gif image/gif.

To load the shared object containing your function, add the following directive at the beginning of the magnus.conf file:

Init fn=load-modules 
		shlib=your-library 
		funcs=send-images

Also, add the following line to the mime.types file:

type=magnus-internal/picgroup exts=picgroup

To execute the custom SAF during the request-response process for an object, add the following code to that object in the obj.conf file. send-images takes an optional parameter, delay, which is not used for this example.


Service method=(GET|HEAD) type=magnus-internal/picgroup fn=send-images

         

The source code for this example is in the service.c file in the install-dir/samples/nsapi directory.

AddLog() Example

The example in this section demonstrates how to implement brief-log, a custom SAF for logging three items of information about a request: the IP address, the method, and the URI, for example, 198.93.95.99 GET /jocelyn/dogs/homesneeded.html.

Installing the AddLog() Example

To load the shared object containing your functions, add the following directive in the Init section of the magnus.conf file:

Init fn=load-modules 
     shlib=your-library 
     funcs=brief-init,brief-log

To call brief-init to open the log file, add the following code to the Init section in magnus.conf. This line must come after the one that loads the library containing brief-init.

Init fn=brief-init 
     file=/tmp/brief.log

To execute your custom SAF during the AddLog stage for an object, add the following line to that object in the obj.conf file:

AddLog fn=brief-log

The source code for this example is in addlog.c file in the install-dir/samples/nsapi directory.

Quality of Service() Example

The code for the qos-handler (AuthTrans) and qos-error (Error) SAFs is provided in case you want to define your own SAFs for quality of service handling.

For more information about predefined SAFs, see the Sun Java System Web Server 7.0 Update 3 Administrator’s Configuration File Reference.

Installing the Quality of Service() Example

Inside the default object in obj.conf, add the following AuthTrans and Error directives:


AuthTrans fn=qos-handler
...
Error fn=qos-error code=503

         

The source code for this example is in the qos.c file in the samples/nsapi subdirectory of the server root directory.