obj.conf
file, from the server, and from previous SAFs.
Here is the C interface for a SAF:
The next section discusses the parameters in detail. The SAF returns a result code which indicates whether and how it succeeded. The server uses the result code from each function to determine how to proceed with processing the request. See the section "Result Codes" for details of the result codes.int function(pblock *
pb, Session *
sn, Request *
rq);
pb (parameter block)
-- contains the parameters from the directive that invokes the SAF in the obj.conf
file.
sn (session)
-- contains information relating to a single TCP/IP session.
rq (request)
-- contains information relating to the current request.
pb
parameter is a pointer to a pblock
data structure that contains values specified by the directive that invokes the SAF. A pblock
data structure contains a series of name/value pairs.
For example, a directive that invokes the basic-nsca
function might look like:
AuthTrans fn=basic-ncsa auth-type=basic
dbm=/netscape/server4/userdb/rs
In this case, the pb
parameter passed to basic-ncsa
contains name/value pairs that correspond to auth-type=basic
and dbm=/netscape/server4/userdb/rs
.
NSAPI provides a set of functions for working with pblock
data structures. For example, pblock_findval()
returns the value for a given name in a pblock
. See "Parameter Block Manipulation Routines" for a summary of the most commonly used functions for working with parameter blocks.
sn
parameter is a pointer to a Session
data structure. This parameter contains variables related to an entire session (that is, the time between the opening and closing of the TCP/IP connection between the client and the server). The same sn
pointer is passed to each SAF called within each request for an entire session. The following list describes the most important fields in this data structure.
(See Chapter 5, "NSAPI Function Reference," for information about NSAPI routines for manipulating the Session
data structure):
pblock
containing information about the client such as its IP address, DNS name, or certificate. If the client does not have a DNS name or if it cannot be found, it will be set to the client's IP number. rq
parameter is a pointer to a request
data structure. This parameter contains variables related to the current request, such as the request headers, URI, and local file system path. The same request
pointer is passed to each SAF called in the request-response process for an HTTP request.
The following list describes the most important fields in this data structure (See Chapter 5, "NSAPI Function Reference," for information about NSAPI routines for manipulating the Request
data structure).
pblock
containing the server's "working" variables. This includes anything not specifically found in the following three pblocks. The contents of this pblock
vary depending on the specific request and the type of SAF. For example, an AuthTrans SAF may insert an "auth-user
" parameter into rq->vars
which can be used subsequently by a PathCheck SAF.pblock
containing elements of the HTTP request. This includes the HTTP method (GET, POST, ...), the URI, the protocol (normally HTTP/1.0), and the query string. This pblock
does not normally change throughout the request-response process.pblock
containing all the request headers (such as User-Agent, If-Modified-Since, ...) received from the client in the HTTP request. See Appendix G, "HyperText Transfer Protocol,"for more information about request headers. This pblock
does not normally change throughout the request-response process.rq->srvhdrs
is a pointer to a pblock
containing the response headers (such as Server,
Date, Content-type, Content-length,...) to be sent to the client in the HTTP
response. See Appendix G, "HyperText Transfer Protocol," for more
information about response headers.
rq->directive_is_cacheable
/mfg/proc/item.txt
, and then another client requests /mfg/proc/item.txt
, the server's response is the same as long as /mfg/proc/item.txt
doesn't change between the requests. When the server can avoid calling the SAFs for a request, it can return the response faster.
The flag is set to 0 on entry to each SAF. If you do not set this flag to 1 before your SAF returns, the server does not try to cache the request, and each subsequent request calls your SAF again. If your SAF sets it to 1, and all other SAFs called for this request also set the flag, the server caches the request and does not call your SAF when another request is made for the same resource.
If your SAF performs access control, logging, depends on the client IP address, the user-agent, or any headers the client sends, it should not set directive_is_cacheable
. Otherwise you should set directive_is_cacheable
to 1.
During development, you may disable server caching by adding the following line at the top of the obj.conf
file:
Init fn=cache-init disable=true
Don't forget to stop and start the server after saving the file. This disables server caching so that your SAF will always be called.rq
parameter is the primary mechanism for passing along information throughout the request-response process. On input to a SAF, rq
contains whatever values were inserted or modified by previously executed SAFs. On output, rq
contains any modifications or additional information inserted by the SAF. Some SAFs depend on the existence of specific information provided at an earlier step in the process. For example, a PathCheck SAF retrieves values in rq->vars
which were previously inserted by an AuthTrans SAF.
REQ_ABORTED
should also set the HTTP response status code. If the server finds an Error
directive matching the status code or reason phrase, it executes the SAF specified. If not, the server sends a default HTTP response with the status code and reason phrase plus a short HTML page reflecting the status code and reason phrase for the user. The server then goes to the first AddLog
directive.AddLog
directive.using the NSAPI functions. Each SAF is written for a specific directive.
the source code to create a shared library (.so, .sl,
or.dll)
file.
by editing the obj.conf
file to:
-- Load the shared library file containing your custom SAF(s).
-- Initialize the SAF if necessary.
by editing obj.conf
to call your custom SAF(s) at the appropriate time.
by accessing your server from a browser with a URL that triggers your function.
nsapi/examples/
in the server root directory and also see Chapter 6, "Examples of Custom SAFsS."
The signature for all SAFs is:
For more details on the parameters, see the section "SAF Parameters." The Enterprise Server runs as a multi-threaded single process. On Unix platforms there are actually two processes (a parent and a child) for historical reasons. The parent process performs some initialization and forks the child process. The child process performs further initialization and handles all the HTTP requests. Keep these things in mind when writing your SAF. Write thread-safe code. Blocking may affect performance. Write small functions with parameters and configure them inint function(pblock *
pb, Session *
sn, Request *
rq);
obj.conf
. Carefully check and handle all errors. Also log them so that you can determine the source of problems and fix them.
If necessary, write an initialization function that performs initialization tasks required by your new SAFs. The initialization function has the same signature as other SAFs:
SAFs expect to be able to obtain certain types of information from their parameters. In most cases, parameter block (int function(pblock *
pb, Session *
sn, Request *
rq);
pblock
) data structures provide the fundamental storage mechanism for these parameters A pblock
maintains its data as a collection of name-value pairs. For a summary of the most commonly used functions for working with pblock
structures, see "Parameter Block Manipulation Routines."
When defining a SAF, you do not specifically state which directive it is written for. However, each SAF must be written for a specific directive (such as Init
, AuthTrans
, Service
and so on). Each directive expects its SAFs to do particular things, and your SAF must conform to the expectations of the directive for which it was written. For details of what each directive expects of its SAFs, see the section "Required Behavior of SAFs for Each Directive."
nsapi/examples
directory. On Windows NT link to nshttpd3x.lib
or nshttpd40.lib
as appropriate in the plugins/lib
directory.
The include
directory in the server-root directory in Enterprise Server 3.x or in server-root/plugins
in Enterprise Server 4.0 contains the NSAPI header file. All the NSAPI header information is now contained in one file called nsapi.h
.
Init
directive that invokes the load-modules
SAF to obj.conf
.
The syntax for a directive that calls load-modules
is:
Init fn=load-modules shlib=
[path]sharedlibnamefuncs="
SAF1,...,SAFn"
shlib
is the local file system path to the shared library (plugin).funcs
is a comma-separated list of function names to be loaded from the shared library. Function names are case-sensitive. You may use dash (-) in place of underscore (_) in function names. There should be no spaces in the function name list.funcs
list.animations.so
that defines two SAFs do_small_anim()
and do_big_anim()
and also defines the initialization function init_my_animations
, you would add the following directive to load the plugin:
If necessary, also add anInit fn=load-modules shlib=
[path]animations.sofuncs="
do_small_anim,do_big_anim,init_my_animations
"
Init
directive that calls the initialization function for the newly loaded plugin. For example, if you defined the function init_my_new_SAF()
to perform an operation on the maxAnimLoop
parameter, you would a directive such as the following to obj.conf
:
Init fn=init_my_animations
maxAnimLoop=5
obj.conf
to instruct the server to call each custom SAF at the appropriate time. The syntax for directives is:
Directive fn=function-name [name1="value1"]...[nameN="valueN"]
Directive
is one of the server directives, such as Init
, AuthTrans
, and so on.function-name
is the name of the SAF to execute.nameN="valueN"
are the names and values of parameters which are passed to the SAF.obj.conf
or you might need to add more than one directive to provide complete instructions for invoking the new SAF.
For example, if you define a new AuthTrans
or PathCheck
SAF you could just add an appropriate directive in the default object. However, if you define a new Service
SAF to be invoked only when the requested resource is in a particular directory or has a new kind of file extension, you would need to take extra steps.
If your new Service SAF is to be invoked only when the requested resource has a new kind of file extension, you might need to add an entry to the MIME types file so that the type
value gets set properly during the ObjectType
stage. Then you could add a Service
directive to the default object that specifies the desired type
value.
If your new Service
SAF is to be invoked only when the requested resource is in a particular directory, you might need to define a NameTrans
directive that generates a name
or ppath
value that matches another object, and then in the new object you could invoke the new Service
function.
For example, suppose your plugin defines two new SAFs, do_small_anim()
and do_big_anim()
which both take speed
parameters. These functions run animations. All files to be treated as small animations reside in the directory D:/Netscape/server4/docs/animations/small, while all files to be treated as full screen animations reside in the directory D:/Netscape/server4/docs/animations/fullscreen.
To ensure that the new animation functions are invoked whenever a client sends a request for either a small or fullscreen animation, you would add NameTrans
directives to the default object to translate the appropriate URLs to the corresponding pathnames and also assign a name to the request.
NameTrans fn=pfx2dir from="/animations/small"
dir="D:/Netscape/server4/docs/animations/small" name="small_anim"
NameTrans fn=pfx2dir from="/animations/fullscreen"You also need to define objects that contain the
dir="D:/Netscape/server4/docs/animations/fullscreen"
name="fullscreen_anim"
Service
directives that run the animations and specify the speed
parameter.
<Object name="small_anim">
Service fn=do_small_anim speed=40
</Object>
<Object name="fullscreen_anim">
Service fn=do_big_anim speed=20
</Object>
obj.conf
, you need to start and stop the server. On Unix you may execute the shell scripts stop
and start
in the servers home directory. Do not use restart
on Unix since the server will not reload your shared library after it has been loaded once.
On Windows NT you may use the Services Control Panel to stop and start the server. Once you have started the server with your shared library, you'll have to stop it before you can build your shared library again.
You can also use the Server Manager interface to re-load obj.conf
and to start and stop the server.
If there are problems during startup, check the error log.
http://server-name/animations/small
, try requesting a valid resource that starts with that URI.
You should disable caching in your browser so that the server is sure to be accessed. In Navigator you may hold the shift key while clicking the Reload button to ensure that the cache is not used. (Note that the shift-reload trick does not always force the client to fetch images from source if the images are already in the cache.)
You may also wish to disable the server cache using the cache-init
SAF.
Examine the access log and error log to help with debugging.
pblock
data structure include:
pblock_findval()
returns the value for a given name in a pblock
.pblock_nvinsert()
adds a new name-value entry to a pblock
.pblock_remove()
removes a pblock
entry by name from a pblock
. The entry is not disposed. Use param_free()
to free the memory used by the entry.param_free()
frees the memory for the given pblock
entry.pblock_pblock2str()
creates a new string containing all the name-value pairs from a pblock
in the form "name=value name=value
". This can be a useful function for debugging.request_header()
returns the value for a given request header name, reading the headers if necessary. This function must be used when requesting entries from the browser header pblock
(rq->headers
).protocol_status()
sets the HTTP response status code and reason phraseprotocol_start_response()
sends the HTTP response and all HTTP headers to the browser.pool-init
in Chapter 3, "Predefined SAFS for Each Stage in the Request Handling Process."
MALLOC()
FREE()
STRDUP()
REALLOC()
CALLOC()
PERM_MALLOC()
PERM_FREE()
PERM_STRDUP()
PERM_REALLOC()
PERM_CALLOC()
system_fopenRO()
opens a file for read-only access.
system_fopenRW()
opens a file for read-write access, creating the file if necessary.
system_fopenWA()
opens a file for write-append access, creating the file if necessary.
system_fclose()
closes a file.
system_fread()
reads from a file.
system_fwrite()
writes to a file.
system_fwrite_atomic()
locks the given file before writing to it. This avoids interference between simultaneous writes by multiple processes or threads.
netbuf_grab()
reads from a network buffer's socket into the network buffer.
netbuf_getc()
gets a character from a network buffer.
net_write()
writes to the network socket.
systhread_start()
creates a new thread.
systhread_sleep()
puts a thread to sleep for a given time.
crit_init()
creates a new critical section variable.
crit_enter()
gains ownership of a critical section.
crit_exit()
surrenders ownership of a critical section.
crit_terminate()
disposes of a critical section variable.
condvar_init()
creates a new condition variable.
condvar_notify()
awakens any threads blocked on a condition variable.
condvar_wait()
blocks on a condition variable.
condvar_terminate()
disposes of a condition variable.
daemon_atrestart()
(Unix only) registers a user function to be called when the server is sent a restart signal (HUP) or at shutdown.
util_getline()
gets the next line (up to a LF or CRLF) from a buffer.
util_hostname()
gets the local hostname as a fully qualified domain name.
util_later_than()
compares two dates.
util_sprintf()
same as standard library routine sprintf()
.
util_strftime()
same as standard library routine strftime()
.
util_uri_escape()
converts the special characters in a string into URI escaped format.
util_uri_unescape()
converts the URI escaped characters in a string back into special characters.
Init
stage must conform to different requirements than SAFs to be invoked during the Service
stage.
This section outlines the expected behavior of SAFs used at each stage in the request handling process.
rq
parameter is the primary mechanism for passing along information throughout the request-response process. On input to a SAF, rq
contains whatever values were inserted or modified by previously executed SAFs. On output, rq
contains any modifications or additional information inserted by the SAF. Some SAFs depend on the existence of specific information provided at an earlier step in the process. For example, a PathCheck SAF retrieves values in rq->vars
which were previously inserted by an AuthTrans SAF.
rq
and sn
are NULL
.daemon_atrestart()
to clean up.error
parameter into pb
describing the error and return REQ_ABORTED
.REQ_PROCEED
.Authorization
header in rq->headers
which contains the authorization type and uu-encoded user and password information. If header was not sent return REQ_NOACTION
.auth-type
, plus auth-user
and/or auth-group
parameter in rq->vars
to be used later by PathCheck
SAFs.REQ_PROCEED
if the user was successfully authenticated, REQ_NOACTION
otherwise.ppath
in rq->vars
) to convert it into a full local file system path.REQ_PROCEED
if ppath
in rq->vars
contains the full local file system path, or REQ_NOACTION
if not.ppath
in rq->vars
to /URL
. Add url
to rq->vars
with full URL (for example., http://home.netscape.com/
). Return REQ_PROCEED
.auth-type
, auth-user
and/or auth-group
in rq->vars.
REQ_PROCEED
if user (and group) is authorized for this area (ppath
in rq->vars
).WWW-Authenticate
to rq->srvhdrs
with a value such as: Basic; Realm=\"Our private area\"
. Call protocol_status()
to set HTTP response status to PROTOCOL_UNAUTHORIZED
. Return REQ_ABORTED
.content-type
in rq->srvhdrs
already exists, return REQ_NOACTION
.content-type
in rq->srvhdrs
REQ_PROCEED
if content-type
is created, REQ_NOACTION
otherwisetype
, method
, and query
specified in the directive in obj.conf
match the request.rq->srvhdrs
. Insert correct "content-type" in rq->srvhdrs
. rq->srvhdrs
.protocol_status()
to set HTTP response status.protocol_start_response()
to send HTTP response and headers.net_write()
.REQ_PROCEED
if successful, REQ_EXIT
on write error, REQ_ABORTED
on other failures.code
and reason
specified in the directive in obj.conf
match the current error.AddLog
SAFs can use any data available in pb
, sn
, or rq
to log this transaction.REQ_PROCEED
.Last Updated: 08/12/99 14:32:57
Copyright © 1999 Netscape Communications Corporation