magnus.conf
file, which contains information the server uses to configure itself. For example, the file tells the server the port to bind to, the name of the server, the user account to use after start-up, and so on. You can find a sample of the magnus.conf
file on page 74.
Once it has started running, the server waits for requests to come in from client applications (such as Netscape Navigator). When a request comes in, the server uses another file, obj.conf
, to determine if and how it should service the request. You can find a sample obj.conf
file on page 77.
For example, the
obj.conf
file contains directives that can be set up to tell the server whether a user has access to the document they're requesting, and if they have access, to determine (among other things) whether the server should attach information to the document when it sends it to the client. This process is much more detailed, as described here and in the following sections.
The Netscape server responds to a client request by following a prescribed process in which each step is done once for all objects matching the request, then another step is done for all objects, and so on. For example, authorization translation (the first step) is performed on all objects in obj.conf
, and then name translation (the second step) is done for all objects.
How the server uses directives and functions in an object
Translate any authorization information sent by the client into a user and a group. If necessary, decode the message to get the actual request. Also, user authorization is available through user databases.
A URL can simply be kept intact and retrieved as-is (the typical server case), or it can be translated into one of the following:
Perform various tests on the resulting path. Typically, this is done to make sure that it's safe for the given client to retrieve the document.
Identify the MIME type information for the given document. MIME types
can be registered document types such as text/html
and image/gif
, or
they can be internal document identification types.
Internal types always begin with magnus-internal/
, and are used to
select a server function to use to decode the document. (These decoding
routines are used within the server itself; the server system calls these
routines automatically when necessary.)
Select an internal server function to send the result back to the client. This function can be the normal server-service routine, it can return a custom document, or it can run a CGI program.
Record information about the transaction.
Controls how the server responds to the client when it encounters an error.
obj.conf
. You use the syntax:
directiveThe directive is the directive the function belongs to (for example, the AuthTrans directive). You can then send any number of optional parameters to your function as arguments you specify on a directive line infn="
ourfunction"
name1=
value1... nameN
=
valueN
obj.conf
. For example, you could create a function for the NameTrans directive called myfunc1
that takes a URL path as a value and maps it to a hard-coded path specified in your function source code. The line in obj.conf
might look like this:
NameTrans fn="myfunc1" URLpath="/special/docs"The request-response code returned by the function can tell the server to do the following (
REQ
stands for request):REQ_PROCEED
indicates that the function has performed its task without a problem. When a function of an AuthTrans, NameTrans, Service, or Error directive returns this, the server skips any remaining directives of the same type for that object, then moves to the next type of directive. However, when the function is of a PathCheck, ObjectType, or AddLog directive, a REQ_PROCEED
value has the same effect as REQ_NOACTION
--the server moves to the next line.
REQ_NOACTION
indicates that the function found conditions such that it did not perform its intended action. The meaning of this depends on the step being performed, but the server moves to the next line in the object file.
REQ_ABORTED
indicates that an error occurred and that the request (not necessarily the session) should be terminated. An error message should be sent to the client.
REQ_EXIT
should be used only when a read or write error has occurred while talking to the client, and the entire session cannot continue.
Note
Before you can use any of your plug-in functions, you must configure the
server to load the functions. You do this with the Init-class function
load_modules in obj.conf
. The full process is described later in this
chapter.
magnus.conf
is the server's main configuration file. It controls aspects of the server operation not related to documents, such as host name and port.
obj.conf
is the server's object configuration file. It controls access to the server and manages the files and directories the server can send to clients.
mime.types
is the file the server uses to convert file-name extensions such as .GIF into a MIME type like image/gif.
admpw
is the administrative password file. Its format is user:password. The password is DES-encrypted, like /etc/passwd.
magnus.conf
file has the format:
Directive ValueCaution!
If you will be using the Server Manager and hand editing to modify the magnus.conf file, you shouldn't use continuation lines in the file. Instead, keep each configuration command entirely on a single line. If you are absolutely sure you will never use the Server Manager, you can use the backslash continuation convention.Sample magnus.conf file
# Sample magnus.conf file for Netscape web server 2.0 # The server's home--its root directory ServerRoot /usr/ns-home/https-server1 # The server's name ServerName www.netscape.com # Which port? Port 443 # This tells the server to get its objects from obj.conf, and use # the "default" object as the default. LoadObjects obj.conf RootObject default # The logfile for errors, and the file where it should keep # the pid of the master server process. ErrorLog /usr/ns-home/https-server1/logs/errors PidLog /usr/ns-home/https-server1/logs/pid # Which user should the server run as? This is the UNIX user # account name. User http # Processes - number of processes to spawn MaxProcs 1 MinThreads 4 MaxThreads 128 # Use DNS? (turn this off for performance reasons) DNS on # Security directives: is security on, where is my keyfile, # which ciphers should I support (Ciphers directive is on the # US version only) Security on Keyfile ServerKey.db Certfile ServerCertFor the details about the directives, see "Directives in magnus.conf" on page 205.
The obj.conf file
The object configuration file, called obj.conf, uses objects to control how the server handles documents.
Objects (also referred to as resources) are settings that tell the server how to treat documents, CGI programs, directories, imagemap files, and so on. You can define objects in two ways:
Using this object grouping scheme, you can specify single resources with
their complete URI, whole directories with the path followed by the
wildcard pattern "/*
", and various other patterns such as "*.html
". You
can then configure the settings you want to use for that object (for example,
caching or denying access based on the server's host name or a string
within a URL).
Using configuration styles makes it easy to configure scattered directories. For example, if user home directories appear in several places, you use one configuration style instead of configuring each directory separately.
Also, when you use cgi-bin
directories, all files are treated as programs
and are run rather than sent. If you create a CGI configuration style and
assign the configuration style to CGI programs (using name translation),
then you can have any number of CGI directories and they all use the
configuration style configuration.
</Object> <Object name=cgi> Directives ... </Object>You can use wildcard patterns to control what is grouped in the object, or you use a name to create a configuration style. <Object ppath=wildcardpattern> Directives ... <Client dns=wildcardpattern> Directives ... </Client> You then specify one or more directives to control what the server does when it encounters anything that uses the configuration style or that matches the wildcard pattern specified with ppath. For more on the concept of
ppath
( "partial path") see "NameTrans" on page 81.
You can also set options for specific client hosts. This is a powerful feature because, unlike other servers where a host either can or cannot access a document, you make the server act differently for a client depending on the document they access. Although <Client> sections are not required in an </Object> section, you can specify one or more--so the server acts differently based both on who requests something and what they request.
Directive syntax
Each command line in the file has the format:
Directive fn=function [parameter1=value1]...[parameterN=valueN]
Directive identifies an aspect of server operation. This string is case insensitive and must appear at the beginning of a line.
Function is the name of a function. It can be a built-in function (see Appendix B, "Server configuration files") or a plug-in function (see Chapter 5, "Creating server plug-in functions"). Its format depends on the directive.
The parameter and value pairs represent parameters given to the directive.
A sample object
The following sample object applies to the /user/public/ directory.
When the server receives a request for a document in this directory, it doesn't send the document. Instead, it denies the existence of any files or subdirectories and displays the "not found" error message.
<Object ppath="/user/public/*">
PathCheck fn=deny-existence
Service fn=server-retrieve
</Object>
The Service directive tells the server to get the documents by default.
Sample obj.conf file
#
# Sample obj.conf file for Netscape web server 2.0.
#
# This file was automatically generated by the server.
# Edit at your own risk.
# The default object. This is what the server uses if none of the other
# objects fit.
#
# This one has a CGI directory specified in /usr/local/bin/cgi,
# a directory mapping to a bigger disk in /gig-drive/sales,
# and a document root of /usr/http-docs
#
# Initializations, such as log files and loading NSAPI libraries
Init fn="flex-init" format.access="%Ses->client.ip% - %Req->vars.auth-user%
[%SYSDATE%] "%Req->reqpb.clf-request%" %Req->srvhdrs.clf-status%
%Req->srvhdrs.content-length%" access="/usr/ns-home/httpd-80/logs/access"
Init fn=load-types mime-types=mime.types
Init fn="dns-cache-init" cache-size="512" expire="1200"
<Object name="default">
NameTrans from="/ns-icons" fn="pfx2dir" dir="/usr/ns-home/ns-icons"
NameTrans from="/cgi-bin" dfn="pfx2dir" dir="/usr/local/bin/cgi" name="cgi"
NameTrans from="/sales" fn="pfx2dir" dir="/gig-drive/sales"
NameTrans root="/usr/http-docs" fn="document-root"
PathCheck fn="unix-uri-clean"
PathCheck fn="find-pathinfo"
PathCheck index-names="index.html,home.html" fn="find-index"
ObjectType fn="type-by-extension"
ObjectType fn="force-type" type="text/plain"
Service fn="imagemap" method="(GET|HEAD)" type="magnus-internal/imagemap"
Service fn="index-common" method="(GET|HEAD)" type="magnus-internal/directory"
Service fn="send-cgi" type="magnus-internal/cgi"
Service fn="send-file" method="(GET|HEAD)" type="*~magnus-internal/*"
AddLog fn="flex-log" name="access"
</Object>
# All CGI directories have these configuration options set
<Object name="cgi">
ObjectType fn="force-type" type="magnus-internal/cgi"
Service fn="send-cgi"
</Object>
Required objects for obj.conf
There are two objects that must be in the obj.conf file to make the Server Manager work for your server. These functions control local file access and CGI execution.
The following sections describe the objects that must be in obj.conf.
The default object
<Object name="default">
NameTrans fn="pfx2dir" from="/mc-icons" dir="/usr/home/mc-icons"
NameTrans fn="document-root" root="/usr/http-docs"
PathCheck fn="unix-uri-clean"
PathCheck fn="find-pathinfo"
ObjectType fn="type-by-extension"
ObjectType fn="force-type" type="text/plain"
Service fn="imagemap" method="(GET|HEAD)"
type="magnus-internal/imagemap"
Service fn="index-common" method="(GET|HEAD)"
type="magnus-internal/directory"
Service fn="send-file" method="(GET|HEAD)"
type="*~magnus-internal/*"
</Object>
CGI object
This object controls the admin form handler scripts and should read exactly as follows:
<Object name="cgi">
ObjectType fn="force-type" type="magnus-internal/cgi"
Service fn="send-cgi"
</Object>
Data in the server: the parameter block
The server stores variables in name-value pairs. The parameter block, or pblock (see page 198), is a hash table keyed on the name string. The parameter block maps these name strings onto their value character strings. Basically, server application functions use parameter block to get, change, add, and remove name-value pairs of data.
All server application functions (regardless of class) are described by the following prototype:
int function(pblock *pb, Session *sn, Request *rq);
The parameter pb is the parameter block containing the parameters given by the site administrator for this function invocation.
The parameter sn is a Session data structure (see page 197) that holds variables that apply throughout an entire session (the time between the opening and closing of the connection between the client and the server).
The parameter rq is a Request data structure (see page 199) contains the server's working variables.
Details for each directive/step
The following sections list the special conditions that exist in the parameter-block variables of the Request structure, and the request-response codes for each class of server function.
AuthTrans
The server splits authorization into two phases.
rq->vars
parameter block.
Request->vars
parameter block upon entry to an AuthTrans-class function. Upon successful completion of an AuthTrans-class function, the following parameter block variables are customarily set: auth-type
identifies the authorization type. Currently, only basic
is defined for HTTP Basic user authorization.
auth-user
gives the name of the client user as verified by the function.
REQ_PROCEED
if successful.
REQ_NOACTION
if the authorization was unsuccessful.
REQ_ABORTED
if the request is to be aborted.
rq->vars
parameter block for NameTrans-class functions when the NameTrans step begins: ppath
is a Partial Path. Initially, it is the virtual path given to the server by the client. If other NameTrans-class functions have altered the value of ppath
, it might be a partially translated path. A function can change the value of ppath
regardless of the current request-response code.
name
, if inserted into the parameter block by your function, dictates that the given named object should be added to the set of active objects for this request. The directives in that object will be applied.
REQ_PROCEED
: Indicates that a name translation was performed, and that name translation for this object should not continue. This means the server moves to the next directive type in the object as defined in obj.conf
(usually PathCheck, either in a user-defined object or the default object). When REQ_PROCEED
is returned by a NameTrans-class function, path
is automatically created from ppath
. These two persist until the request is completed.
REQ_NOACTION
indicates that no final name translation was applied by the function. This doesn't mean that ppath
was not changed. The server continues applying the rest of the object's NameTrans functions.
REQ_ABORTED
indicates that the request has encountered an error and that an error message should be sent to the client. No functions are called after the function returns this, except any functions that are designated error handlers.
REQ_EXIT
indicates that an I/O error occurred while talking with the client. The request should be aborted and no error message should be sent.
Request->vars
parameter block: the value of path
is the path resulting from the execution of all NameTrans directives. Any variables that have been created by previous directives are also available.
Upon return from a PathCheck-class function, a request-response code of REQ_PROCEED
and REQ_NOACTION
indicates success.
path
in Request->vars
and the variables defined by the previous directives. Upon return from an ObjectType-class function, a request-response code of REQ_PROCEED
and REQ_NOACTION
indicates success.
The server's built-in functions provide mechanisms for typing files natively to the machine's operating system. On most systems, this consists of file name extension recognition code.
path
in Request->vars
and any variables defined by the previous directives.
Upon return from a Service-class function, the request-response codes have the following meaning: REQ_PROCEED
indicates that the response has been sent to the client successfully.
REQ_NOACTION
indicates that the function was not applied. The server should look at the next Service directives.
REQ_ABORTED
indicates that an error has occurred and the server should send a message to the client.
REQ_EXIT
indicates that the connection to the client should end. For a typical example, errors indicate the client is no longer listening, but those errors should be logged.
int protocol_start_response(Session *sn, Request *rq);If the protocol_start_response function returns
REQ_NOACTION
, then the actual response should be skipped and the application function should return successfully. The only other value that protocol_start_response returns is REQ_PROCEED
.
If cross platform considerations are not required, then operating-system specific I/O calls can be made by Service-class functions.
Session
and Request
parameters are NULL. The parameter pblock
is filled with information from the server's configuration file (obj.conf
).
Static data should be limited to read-only data if possible. If the program can be sure that no race conditions exist, it can make the data read/write. Other data media (such as databases) will need to employ some method of locking to ensure that only one process or thread is accessing the data at a time. The routines in the base/sem.h
header file are used to coordinate processes, and those in the base/crit.h
file are used to coordinate threads.
Upon failure, plug-in Init-class functions should return REQ_ABORTED
and insert into their parameter block a variable named error
that contains a string describing the error, for logging Any other request-response code is considered success.
If the server is restarted, the Init-class functions might need to be terminated before they are started again by the server code. For this purpose, the server provides the following function:
void daemon_atrestart(void (*fn)(void *), void *data)The given callback
fn
is called by the server when the server is restarted. The data pointer is given to the function as its argument.
Note
The Netscape web servers do not call the callbacks upon server termination, only upon restart.
Some new features in version 2.0
The version 2.0 web servers provide several new features, including multi-threading (both on Unix and on Windows NT), caching of requests, and multihoming.
Threading
A thread is a single independent stream of execution within a program. A critical section is a section of program code that must be executed by only one thread at a time. Portions of code that perform such tasks as switching between threads or updating a record in a database are critical sections. A condition variable is a thread-synchronization variable that lets the user specify arbitrary conditions on which to block.
In addition to the Windows NT servers being multithreaded, all of the 2.0 Unix web servers are multithreaded. There are abstractions in base/systhr.h
and base/crit.h
for threads, critical sections, and condition variables.
The Unix servers are still capable of running in multiple-process mode. Each process then has a pool of threads that it uses to answer requests. If your server plug-in modules are not thread-safe, you can run the server with one thread per process to simulate the 1.1 server architecture; however this can result in a performance loss. You can run one process with multiple threads to simplify programming. This lets you share context without using shared memory. However, high traffic sites that use CGI should use several processes (2-8) with fewer maximum threads per process. For example, if you normally run one process with 128 threads, run 4 processes with 32 maximum threads each if your site serves a very high volume. This avoids large virtual address spaces for a single process.
New thread manipulation calls exist in base/systhr.h
. The following functions can manipulate threads:
base/sem.h
remain the same and provide server-wide mutual exclusion. Under Windows NT, these are simply critical sections that apply to all threads in the server process. Under Unix, these primitives operate on all threads in all processes of the server, so they are very heavyweight. They should only be used to protect access to process-shared resources such as shared memory and files.
New calls exist in base/crit.h
that provide process-local critical sections and condition variables for Windows NT and Unix. These calls only affect threads in the current process. Critical sections are simply a lock that can be owned by only one thread at a time. They can be recursively entered. Condition variables are used in conjunction with a critical section to provide "wait" and "notify" primitives.
On IRIX, Solaris 2.x, and OSF/1, the operating systems provide threading support, and multithreaded versions of libc
. On those systems, you can call most libc
routines safely. One notable exception is that you must use the localtime_r and gmtime_r functions instead of the localtime and gmtime functions respectively. Many other functions also must be called in their reentrant form. Check your system's documentation for details.
On systems that don't have threading support, we provide the threading via user-level context switches. The server doesn't currently try to perform thread preemption, which means that you can still use libc calls that aren't re-entrant. Thread switching is performed when a lock is used, when the API I/O functions such as net_read are called, and when a systhread_yield function is explicitly called. This also means that if your server plug-in function makes a system call that will block, you will block the process that your thread is running in (thus blocking all threads in that process). DNS calls such as gethostbyaddr are an example of a call which will block the process, however the API function session_dns will not block the process.
Under IRIX, you must compile with -D_SGI_MP_SOURCE
.
Under Solaris, you must compile with -D_REENTRANT
.
Under OSF/1, you must compile with -threads
.
/mfg/proc/item.txt
, and then another client requests /mfg/proc/item.txt
, the server's response will be the same as long as /mfg/proc/item.txt
doesn't change between the requests. When the server can avoid calling the NSAPI functions for a request, it can return the responses faster.
There is a new variable called directive_is_cachable in the Request structure in 2.0. By default, this variable is set to 0
when calling your NSAPI functions. If you do not set this variable to 1
before your function returns, the server will not try to cache the request, and each subsequent request will call your function again. If you set it to 1
, the server may not call your function when the next client makes the same request.
You should cache requests that do not depend on some aspect of the client to determine how they are returned. If your function performs access control, logging, switches data based on user-agent, or anything similar, you should not mark your directive as cachable. If your function is doing something which does not depend on the client IP address or the headers the client sends, then you can mark your directive as cachable.
obj.conf
directives conditional on the client's IP address, you can also specify that they only be executed when the URL host is a specific pattern. For example,
<Client urlhost=www.(any|such).com> NameTrans fn=my-nametrans from=/anysuchdir </Client>
placed in the default
object will call my-nametrans
only when the browser thinks it is accessing www.any.com or www.such.com. Similarly,
<Client urlhost=*~www.(any|such).com> NameTrans fn=my-nametrans from=/anysuchdir </Client>
will apply my-nametrans
to every except those who access www.any.com and www.such.com including browsers that don't send the Host: header.