Write your custom SAFs using NSAPI functions. For a summary of some of the most commonly used NSAPI functions, see Overview of NSAPI C Functions and for available routines, see Chapter 6, NSAPI Function and Macro Reference.
For examples of custom SAFs, see Chapter 4, Examples of Custom SAFs and Filters.
The signature for all SAFs is as follows:
int function(pblock *pb, Session *sn, Request *rq);
For more details on the parameters, see SAF Parameters.
You must register your SAFs with the server. SAFs may be registered using the funcs parameter of the load-modules Init SAF or by a call to func_insert. A plug-in may define a nspai_module_init function that is used to call func_insert and perform any other initialization tasks. For more information, see nsapi_module_init() Function and func_insert() Function.
The server runs as a multi-threaded single process. On UNIX platforms, the server runs 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 of the HTTP requests.
Keep the following in mind when writing your SAF:
Write thread-safe code
Blocking can affect performance
Write small functions with parameters and configure the parameters in obj.conf
Carefully check and handle all errors and log the errors so 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 must be named nsapi_module_init and has the same signature as other SAFs:
int nsapi_module_init(pblock *pb, Session *sn, Request *rq);
SAFs should to be able to obtain certain types of information from their parameters. In most cases, parameter block (pblock) data structures provide the fundamental storage mechanism for these parameters. 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 AuthTrans, Service, and so on. Each directive requires its SAFs to behave in particular ways, and your SAF must conform to the requirements of the directive for which it was written. For details on what each directive requires of its SAFs, see Required Behavior of SAFs for Each Directive.