<?xml version="1.0"?>
<!DOCTYPE gsdoc PUBLIC "-//GNUstep//DTD gsdoc 1.0.4//EN" "http://www.gnustep.org/gsdoc-1_0_4.dtd">
<gsdoc base="WebServer">
  <head>
    <title>WebServer documentation</title>
    <author name="Richard Frith-Macdonald">
      <email address="rfm@gnu.org">
        rfm@gnu.org
      </email>
    </author>
    <version>39692</version>
    <date>2016-04-25 12:08:15 +0100 (Mon, 25 Apr 2016)</date>
    <copy>2004-2010 Free Software Foundation, Inc.</copy>
  </head>
  <body>
    <front><contents /></front>
    <chapter>
      <heading>The WebServer class</heading>
      <section>
        <heading>What is the WebServer class?</heading>
        <p>
          The WebServer class provides the framework for a GNUstep
          program to act as an HTTP or HTTPS server for simple
          applications. <br /> It does not attempt to be
          a general-purpose web server, but is rather intended to
          permit a program to easily handle requests from
          automated systems which are intended to control,
          monitor, or use the services provided by the program
          in which the class is embedded. <br /> The emphasis is on
          making it robust/reliable/simple, so you can rapidly
          develop software using it. <br /> By default, it is a
          single-threaded, single-process system using
          asynchronous I/O, so you can easily run it under
          debug in gdb to fix any bugs in your delegate object.
          <br /> For performance, it can also operate as a
          massively multi-threaded process, with separate I/O
          threads handling groups of hundreds or thousands of
          simultaneous connections, and a pool of
          processing threads handling parsing of incoming
          requests.
        </p>
        <p>
          The class is controlled by a few straightforward settings
          and basically operates by handing over requests to its
          delegate. The delegate must at least implement the
          <ref type="method" id="-processRequest:response:for:" class="(WebServerDelegate)">[&lt;WebServerDelegate&gt;-processRequest:response:for:]</ref> method.
        </p>
        <p>
          Built-in facilities include -
        </p>
        <list>
          <item>
            Parsing of parameter string in request URL
          </item>
          <item>
            Parsing of url encoded form data in a POST request
          </item>
          <item>
            Parsing of form encoded data in a POST request
          </item>
          <item>
            Substitution into template pages on output
          </item>
          <item>SSL support</item>
          <item>HTTP Basic authentication</item>
          <item>Limit access by IP address</item>
          <item>
            Limit total number of simultaneous connections
          </item>
          <item>
            Limit number of simultaneous connections from one
            address
          </item>
          <item>Limit idle time permitted on a connection</item>
          <item>Limit size of request headers permitted</item>
          <item>Limit size of request body permitted</item>
        </list>
      </section>
      <section>
        <heading>Performance and threading</heading>
        <p>
          The WebServer class essentially works using asynchronous
          I/O in a single thread. The asynchronous I/O mechanism is
          capably of reading a request of up to the operating
          systems network buffer size in a single operation and
          similarly writing out a response of up to the
          operating system's network buffer size. <br /> As
          <strong>long</strong> as requests and responses are
          within those limits, it can be assumed that slow
          processing of a request in the
          <ref type="method" id="-processRequest:response:for:" class="(WebServerDelegate)">[&lt;WebServerDelegate&gt;-processRequest:response:for:]</ref> method will have little impact on efficiency as the WebServer read request and write responses as rapidly as the delegates processing can handle them. <br /> If however the I/O sizes are larger than the buffers, then writing a response will need to be multiple operations and each buffer full of data may need to wait for the next call to the processing method before it can be sent. <br /> So, for large request/response sizes, or other cases where processing a single request at a time is a problem, the WebServer class provides a simple mechanism for supporting multithreaded use.
        </p>
        <p>
          To use multiple threads, all you need to do is have the
          delegate implementation of
          <ref type="method" id="-processRequest:response:for:" class="(WebServerDelegate)">[&lt;WebServerDelegate&gt;-processRequest:response:for:]</ref> pass processing to another thread and return <code>NO</code>. When processing is complete, the delegate calls <ref type="method" id="-completedWithResponse:">-completedWithResponse:</ref> to pass the response back to the WebServer instance for delivery to the client. <br /> NB. the <ref type="method" id="-completedWithResponse:">-completedWithResponse:</ref> method is safe to call from any thread but all other methods of the class should be called only from the master thread. If a delegate needs to call methods of the WebServer instance in order to handle a request, it should do so in the <ref type="method" id="-processRequest:response:for:" class="(WebServerDelegate)">[&lt;WebServerDelegate&gt;-processRequest:response:for:]</ref> method before handing control to another thread.
        </p>
        <p>
          If the simple threading outlined above is not sufficient
          for your appplication, a more agressive threading scheme
          is available. <br /> You may call the
          <ref type="method" id="-setIOThreads:andPool:">
            -setIOThreads:andPool:
          </ref>
          method to ask the WebServer instance to use threading
          internally itself. In this case the low-level I/O
          operations will be shared across the specified
          number of I/O threads instead of occurring in the
          master thread (makes sense if you need to handle a
          very large number of simultaneous connections). In
          addition, the parsing of the incoming HTTP request
          and the generation of the raw data of the outgoing
          response are performed using threads from the thread
          pool, so that the I/O threads can concentrate on the
          low level communications.
        </p>
        <p>
          With the use of a thread pool, you muse be aware that
          the
          <ref type="method" id="-preProcessRequest:response:for:">
            -preProcessRequest:response:for:
          </ref>
          method will be executed by a thread from the pool
          rather than by the master thread. <br /> This may be
          useful if you wish to split the processing into part
          which is thread-safe, and part which uses complex
          interacting data structures which are hard to
          make safe (done in the main processing method).
        </p>
      </section>
    </chapter>
    <chapter>
      <heading>
        Software documentation for the WebServer class
      </heading>
      <class name="WebServer" super="NSObject">
        <declared>WebServer.h</declared>
        <desc>
          <p>
            You create an instance of the WebServer class in order
            to handle incoming HTTP or HTTPS requests on a single
            port.
          </p>
          <p>
            Before use, it must be configured using the
            <ref type="method" id="-setAddress:port:secure:">
              -setAddress:port:secure:
            </ref>
            method to specify the address and port and if/how
            SSL is to be used.
          </p>
          <p>
            You must also set a delegate to handle incoming
            requests, and may specify a maximum number of
            simultaneous connections which may be in
            progress etc.
          </p>
          <p>
            In addition to the options which may be set directly in
            the class, you can provide some configuration via the
            standard NSDefaults class. This information is set
            at initialisation of an instance and the class
            recognises the following defaults keys -
          </p>
          <deflist>
            <term>WebServerHosts</term>
            <desc>
              An array of host IP addresses to list the hosts
              permitted to send requests to the server. If
              defined, requests from other hosts will be
              rejected (with an HTTP 403 response). It may be
              better to use firewalling to control this sort of
              thing.
            </desc>
            <term>WebServerQuiet</term>
            <desc>
              An array of host IP addresses to refrain from logging
              ... this is useful if (for instance) you have a
              monitoring process which sends requests to the
              server to be sure it's alive, and don't want to
              log all the connections from this monitor. <br /> Not
              only do we refrain from logging anything but
              exceptional events about these hosts,
              connections and requests by these hosts are
              not counted in statistics we generate.
            </desc>
            <term>ReverseHostLookup</term>
            <desc>
              A boolean (default <code>NO</code>) which specifies
              whether the server should lookup the host name
              for each incoming connection, and refuse connections
              where no host can be found. The downside of
              enabling this is that host lookups can be slow
              and cause performance problems.
            </desc>
          </deflist>
          <p>
            To shut down the WebServer, you must call
            <ref type="method" id="-setAddress:port:secure:">
              -setAddress:port:secure:
            </ref>
            with <code>nil</code> arguments. This will stop the
            server listening for incoming connections and wait
            for any existing connections to be closed (or to time
            out). <br /> NB. Once a WebServer instance has been
            started listening on a port, it is not OK to simply
            release it without shutting it down... doing that
            will cause a leak of memory and resources as the
            instance will continue to operate.
          </p>
        </desc>
        <method type="NSURL*" factory="yes">
          <sel>baseURLForRequest:</sel>
          <arg type="WebServerRequest*">request</arg>
          <desc>
            Returns the base URL used by the remote client to
            send the <var>request</var>.
          </desc>
        </method>
        <method type="NSUInteger" factory="yes">
          <sel>decodeURLEncodedForm:</sel>
          <arg type="NSData*">data</arg>
          <sel>into:</sel>
          <arg type="NSMutableDictionary*">dict</arg>
          <desc>
            Same as the instance method of the same name.
          </desc>
        </method>
        <method type="NSUInteger" factory="yes">
          <sel>encodeURLEncodedForm:</sel>
          <arg type="NSDictionary*">dict</arg>
          <sel>into:</sel>
          <arg type="NSMutableData*">data</arg>
          <desc>
            Same as the instance method of the same name.
          </desc>
        </method>
        <method type="NSString*" factory="yes">
          <sel>escapeHTML:</sel>
          <arg type="NSString*">str</arg>
          <desc>
            Same as the instance method of the same name.
          </desc>
        </method>
        <method type="NSURL*" factory="yes">
          <sel>linkPath:</sel>
          <arg type="NSString*">newPath</arg>
          <sel>relative:</sel>
          <arg type="NSURL*">oldURL</arg>
          <sel>query:</sel>
          <arg type="NSDictionary*">fields</arg>
          <vararg />
          <desc>
            Returns a new URL formed by putting the
            <var>newPath</var> in the <var>oldURL</var> and
            appending a query string containing the
            <var>fields</var> specified in the <var>fields</var>
            argument (optionally extended/overridden by any
            other <var>fields</var> defined as key/value pairs in
            the <code>nil</code> terminated list of additional
            arguments. <br /> If the <var>oldURL</var> is
            <code>nil</code>, then the new URL will be a
            relative URL containing just the path and query
            string. <br /> If <var>newPath</var> is an absolute
            path, it replaces the path from <var>oldURL</var>,
            otherwise it replaces the last path component
            from uldURL.
          </desc>
        </method>
        <method type="BOOL" factory="yes">
          <sel>matchIP:</sel>
          <arg type="NSString*">address</arg>
          <sel>to:</sel>
          <arg type="NSString*">pattern</arg>
          <desc>
            Convenience function to check to see if a
            particular IP <var>address</var> matches
            anything in a comma separated list of IP addresses
            or masks. <br /> This currently handles simple IPv4
            addresses, and masks in the format
            nnn.nnn.nnn.nnn/bb where bb is the
            number of bits of the mask to match against the
            <var>address</var> (eg. 192.168.11.0/24).
          </desc>
        </method>
        <method type="NSData*" factory="yes">
          <sel>parameter:</sel>
          <arg type="NSString*">name</arg>
          <sel>at:</sel>
          <arg type="NSUInteger">index</arg>
          <sel>from:</sel>
          <arg type="NSDictionary*">params</arg>
          <desc>
            Same as the instance method of the same
            <var>name</var>.
          </desc>
        </method>
        <method type="NSString*" factory="yes">
          <sel>parameterString:</sel>
          <arg type="NSString*">name</arg>
          <sel>at:</sel>
          <arg type="NSUInteger">index</arg>
          <sel>from:</sel>
          <arg type="NSDictionary*">params</arg>
          <sel>charset:</sel>
          <arg type="NSString*">charset</arg>
          <desc>
            Same as the instance method of the same
            <var>name</var>.
          </desc>
        </method>
        <method type="BOOL" factory="yes">
          <sel>redirectRequest:</sel>
          <arg type="WebServerRequest*">request</arg>
          <sel>response:</sel>
          <arg type="WebServerResponse*">response</arg>
          <sel>to:</sel>
          <arg type="id">destination</arg>
          <desc>
            Convenience method to set up a temporary
            redirect to the specified URL using the supplied
            <var>response</var> data. The method returns
            <code>YES</code> so that it is reasonable to pass
            its return value back directly as the return value for
            a call to the
            <ref type="method" id="-processRequest:response:for:" class="(WebServerDelegate)">[&lt;WebServerDelegate&gt;-processRequest:response:for:]</ref> method. <br /> If <var>destination</var> is an NSURL, the redirection is done to the specified location, otherwise arguments description is taken as a local path to be used with the base URL of the <var>request</var>.
          </desc>
        </method>
        <method type="BOOL">
          <sel>accessRequest:</sel>
          <arg type="WebServerRequest*">request</arg>
          <sel>response:</sel>
          <arg type="WebServerResponse*">response</arg>
          <desc>
            This method is called for each incoming
            <var>request</var>, and checks that the requested
            resource is accessible (basic user/password access
            control). <br /> The method returns
            <code>YES</code> if access is granted, or returns
            <code>NO</code> and sets the appropriate
            <var>response</var> values if access is refused.
            <br /> If access is refused by this method, the
            delegate is not informed of the <var>request</var>
            at all... so this forms an initial access control
            mechanism, but if it is passed, the delegate is
            still free to implement its own additional access
            control within the
            <ref type="method" id="-processRequest:response:for:" class="(WebServerDelegate)">[&lt;WebServerDelegate&gt;-processRequest:response:for:]</ref> method. <br /> The access control is managed by the <code>WebServerAccess</code> user default, which is a dictionary whose keys are paths, and whose values are dictionaries specifying the access control for those paths. Access control is done on the basis of the longest matching path. <br /> Each access control dictionary contains an authentication realm string (keyed on <em>Realm</em>) and a dictionary containing username/password pairs (keyed on <em>Users</em>). <br /> eg.
<example>
 WebServerAccess = {
   "" = {
     Realm = "general";
     Users = {
       Fred = 1942;
     };
   };
 };
 </example>
          </desc>
        </method>
        <method type="NSString*">
          <sel>address</sel>
          <desc>
            Return the address the receiver listens for
            connections on, or <code>nil</code> if it is
            not listening.
          </desc>
        </method>
        <method type="void">
          <sel>closeConnectionAfter:</sel>
          <arg type="WebServerResponse*">response</arg>
          <desc>
            Instructs the server that the connection handlind
            the current request should be closed once the
            <var>response</var> has been sent back to the client.
          </desc>
        </method>
        <method type="void">
          <sel>completedWithResponse:</sel>
          <arg type="WebServerResponse*">response</arg>
          <desc>
            <p>
              This may only be called in the case where a call to
              the delegate's
              <ref type="method" id="-processRequest:response:for:" class="(WebServerDelegate)">[&lt;WebServerDelegate&gt;-processRequest:response:for:]</ref> method to process a request returned <code>NO</code>, indicating that the delegate would handle the request asynchronously and complete it later.
            </p>
            <p>
              In such a case, the thread handling the request in the
              delegate <em>must</em> call this method upon
              completion (passing in the same request
              parameter that was passed to the delegate) to
              inform the WebServer instance that processing of
              the request has been completed and that it should now
              take over the job of sending the <var>response</var>
              to the client process.
            </p>
            <p>
              If the
              <ref type="method" id="-streamData:withResponse:">
                -streamData:withResponse:
              </ref>
              method has been called with the supplied
              <var>response</var> object, calling this method
              terminated the streamed <var>response</var> to
              the client.
            </p>
          </desc>
        </method>
        <method type="NSArray*">
          <sel>connections</sel>
          <desc>
            Returns an array containing an object representing
            each connection currently active for this server
            instance.
          </desc>
        </method>
        <method type="NSUInteger">
          <sel>decodeURLEncodedForm:</sel>
          <arg type="NSData*">data</arg>
          <sel>into:</sel>
          <arg type="NSMutableDictionary*">dict</arg>
          <desc>
            Decode an application/x-www-form-urlencoded form and
            store its contents into the supplied dictionary.
            <br /> The resulting dictionary keys are strings.
            <br /> The resulting dictionary values are arrays of
            NSData objects. <br /> You probably don't need to
            call this method yourself... more likely you will use
            the
            <ref type="method" id="-parameters:">
              -parameters:
            </ref>
            method instead. <br /> NB. For forms POST-ed using
            <code>multipart/form-data</code> you don't need to
            perform any explicit decoding as this will already
            have been done for you and the decoded form will be
            presented as the request GSMimeDocument subclass.
            The fields of the form will be the component parts of
            the content of the request and can be accessed using
            the standard GSMimeDocument methods. <br /> This method
            returns the number of fields actually decoded.
          </desc>
        </method>
        <method type="id">
          <sel>delegate</sel>
          <desc>
            Return this web server's delegate.
          </desc>
        </method>
        <method type="NSUInteger">
          <sel>encodeURLEncodedForm:</sel>
          <arg type="NSDictionary*">dict</arg>
          <sel>into:</sel>
          <arg type="NSMutableData*">data</arg>
          <desc>
            Encode an application/x-www-form-urlencoded form and
            store its representation in the supplied
            <var>data</var> object. <br /> The dictionary
            contains the form, with keys as <var>data</var>
            objects or strings, and values as arrays of values
            to be placed in the <var>data</var>. Each value in the
            array may be a <var>data</var> object or a string.
            <br /> As a special case, a value may be a
            <var>data</var> object or a string rather than an
            array... this is treated like an array of one value.
            <br /> All non <var>data</var> keys and values are
            converted to <var>data</var> using utf-8
            encoding. <br /> This method returns the number
            of values actually encoded.
          </desc>
        </method>
        <method type="NSString*">
          <sel>escapeHTML:</sel>
          <arg type="NSString*">str</arg>
          <desc>
            Escapes special characters in <var>str</var> for
            use in an HTML page. <br /> This converts &amp; to
            &amp;amp; for instance, and replaces non-ascii
            characters with the appropriate numeric entity
            references.
          </desc>
        </method>
        <method type="NSData*">
          <sel>incrementalDataForRequest:</sel>
          <arg type="WebServerRequest*">request</arg>
          <desc>
            Returns a data object containing any data read for
            the body of a partially read <var>request</var> since
            the last call for the same <var>request</var>.
          </desc>
        </method>
        <method type="id">
          <sel>init</sel>
          <desc>
            Initialises the receiver to run on the
            processes main thread (as returned by
            <ref type="method" id="+mainThread" class="NSThread">
              [NSThread +mainThread]
            </ref>
            .
          </desc>
        </method>
        <method type="id" init="yes">
          <sel>initForThread:</sel>
          <arg type="NSThread*">aThread</arg>
          <desc>
            Initialises the WebServer instance to operate
            using the specified thread as the 'master' thread. If
            <var>aThread</var> is <code>nil</code>,
            <ref type="method" id="+mainThread" class="NSThread">
              [NSThread +mainThread]
            </ref>
            is used as the master thread for the newly initialised
            instance. <br /> If the current thread is not the
            same as the specified master thread, this method will
            not return until the master thread's run loop had run
            to handle the initialisation.
          </desc>
        </method>
        <method type="BOOL">
          <sel>isCompletedRequest:</sel>
          <arg type="WebServerRequest*">request</arg>
          <desc>
            Returns <code>YES</code> if the <var>request</var>
            has been completely read, <code>NO</code> if it still
            needs more data to be read from the client and parsed
            before it is complete (ie incremental parsing is in
            progress).
          </desc>
        </method>
        <method type="BOOL">
          <sel>isSecure</sel>
          <desc>
            Returns <code>YES</code> if the server is for HTTPS
            (encrypted connections), <code>NO</code>
            otherwise.
          </desc>
        </method>
        <method type="NSData*">
          <sel>parameter:</sel>
          <arg type="NSString*">name</arg>
          <sel>at:</sel>
          <arg type="NSUInteger">index</arg>
          <sel>from:</sel>
          <arg type="NSDictionary*">params</arg>
          <desc>
            Returns the index'th data parameter for the
            specified <var>name</var>. <br /> Matching of
            names is case-insensitive <br /> If there are no data
            items for the <var>name</var>, or if the
            <var>index</var> is too large for the number of items
            which exist, this returns <code>nil</code>.
          </desc>
        </method>
        <method type="NSData*">
          <sel>parameter:</sel>
          <arg type="NSString*">name</arg>
          <sel>from:</sel>
          <arg type="NSDictionary*">params</arg>
          <desc>
            Calls
            <ref type="method" id="-parameter:at:from:">
              -parameter:at:from:
            </ref>
            with an index of zero.
          </desc>
        </method>
        <method type="NSString*">
          <sel>parameterString:</sel>
          <arg type="NSString*">name</arg>
          <sel>at:</sel>
          <arg type="NSUInteger">index</arg>
          <sel>from:</sel>
          <arg type="NSDictionary*">params</arg>
          <desc>
            Calls
            <ref type="method" id="-parameterString:at:from:charset:">
              -parameterString:at:from:charset:
            </ref>
            with a <code>nil</code> charset so that UTF-8 encoding
            is used for string conversion.
          </desc>
        </method>
        <method type="NSString*">
          <sel>parameterString:</sel>
          <arg type="NSString*">name</arg>
          <sel>at:</sel>
          <arg type="NSUInteger">index</arg>
          <sel>from:</sel>
          <arg type="NSDictionary*">params</arg>
          <sel>charset:</sel>
          <arg type="NSString*">charset</arg>
          <desc>
            Calls
            <ref type="method" id="-parameter:at:from:">
              -parameter:at:from:
            </ref>
            and, if the result is non-nil converts the data to a
            string using the specified mime characterset, (if
            <var>charset</var> is <code>nil</code>, UTF-8 is
            used).
          </desc>
        </method>
        <method type="NSString*">
          <sel>parameterString:</sel>
          <arg type="NSString*">name</arg>
          <sel>from:</sel>
          <arg type="NSDictionary*">params</arg>
          <desc>
            Calls
            <ref type="method" id="-parameterString:at:from:charset:">
              -parameterString:at:from:charset:
            </ref>
            with an index of zero and a <code>nil</code> value for
            charset (which causes data to be treated as UTF-8).
          </desc>
        </method>
        <method type="NSString*">
          <sel>parameterString:</sel>
          <arg type="NSString*">name</arg>
          <sel>from:</sel>
          <arg type="NSDictionary*">params</arg>
          <sel>charset:</sel>
          <arg type="NSString*">charset</arg>
          <desc>
            Calls
            <ref type="method" id="-parameterString:at:from:charset:">
              -parameterString:at:from:charset:
            </ref>
            with an index of zero.
          </desc>
        </method>
        <method type="NSMutableDictionary*">
          <sel>parameters:</sel>
          <arg type="WebServerRequest*">request</arg>
          <desc>
            Extracts <var>request</var> parameters from the
            HTTP query string and from the <var>request</var> body
            (if it was application/x-www-form-urlencoded or
            multipart/form-data) and return the
            extracted parameters as a mutable dictionary
            whose keys are the parameter names and whose values
            are arrays containing the data for each parameter.
            <br /> You should call this no more than once per
            <var>request</var>, storing the result and using it
            as an argument to the methods used to extract particular
            parameters. <br /> Parameters from the
            <var>request</var> data are <em>added</em> to any
            found in the query string. <br /> Values provided as
            <code>multipart/form-data</code> are also available
            in a more flexible format (see
            <ref type="class" id="GSMimeDocument">GSMimeDocument</ref>
              ) as the content of the <var>request</var>.
          </desc>
        </method>
        <method type="NSString*">
          <sel>port</sel>
          <desc>
            Return the port the receiver listens for connections
            on, or <code>nil</code> if it is not listening.
          </desc>
        </method>
        <method type="BOOL">
          <sel>produceResponse:</sel>
          <arg type="WebServerResponse*">aResponse</arg>
          <sel>fromStaticPage:</sel>
          <arg type="NSString*">aPath</arg>
          <sel>using:</sel>
          <arg type="NSDictionary*">map</arg>
          <desc>
            Loads a template file from disk and places it in
            <var>aResponse</var> as content whose mime type is
            determined from the file extension using the
            provided mapping (or a simple built-in default
            mapping if <var>map</var> is <code>nil</code>).
            <br /> If you have a dedicated web server for
            handling static pages (eg images) it is better to
            use that rather than vending static pages using this
            method. It's unlikely that this method can be as
            efficient as a dedicated server. However this
            mechanism is adequate for moderate throughputs.
          </desc>
        </method>
        <method type="BOOL">
          <sel>produceResponse:</sel>
          <arg type="WebServerResponse*">aResponse</arg>
          <sel>fromTemplate:</sel>
          <arg type="NSString*">aPath</arg>
          <sel>using:</sel>
          <arg type="NSDictionary*">map</arg>
          <desc>
            Loads a template file from disk and places it in
            <var>aResponse</var> as content of type 'text/html'
            with a charset of 'utf-8'. <br /> The argument
            <var>aPath</var> is a path relative to the root path
            set using the
            <ref type="method" id="-setRoot:">
              -setRoot:
            </ref>
            method. <br /> Substitutes values into the template
            from <var>map</var> using the
            <ref type="method" id="-substituteFrom:using:into:depth:">
              -substituteFrom:using:into:depth:
            </ref>
            method. <br /> Returns <code>NO</code> if the
            template could not be read or if any substitution
            failed. In this case no value is set in the
            response. <br /> If the response is actually text
            of another type, or you want another characterset used,
            you can change the content type header in the request
            after you call this method. <br /> Note that,
            although the <var>map</var> is nominally an
            NSDictionary instance, it can in fact be any
            object which responds to the
            <ref type="method" id="-objectForKey:" class="NSDictionary">[NSDictionary -objectForKey:]</ref> message by returning a string or <code>nil</code>.
          </desc>
        </method>
        <method type="BOOL">
          <sel>setAddress:</sel>
          <arg type="NSString*">anAddress</arg>
          <sel>port:</sel>
          <arg type="NSString*">aPort</arg>
          <sel>secure:</sel>
          <arg type="NSDictionary*">secure</arg>
          <desc>
            Sets the listenng address, port and security
            information for the receiver... without this
            the receiver will not listen for incoming requests.
            <br /> If <var>anAddress</var> is <code>nil</code>
            or empty, the receiver will listen on all available
            network interfaces. <br /> If <var>secure</var> is
            <code>nil</code> then the receiver listens on
            <var>aPort</var> for HTTP requests. <br /> If
            <var>secure</var> is not <code>nil</code>, the
            receiver listens for HTTPS instead. <br /> If
            <var>secure</var> is a dictionary containing
            <code>CertificateFile</code>, <code>KeyFile</code>
            and <code>Password</code> then the server will use the
            specified certificate and key files (which it
            will access using the password). <br /> The
            <em><var>secure</var></em> dictionary may also contain
            other dictionaries keyed on IP addresses, and if the
            address that an incoming connection arrived on
            matches the key of a dictionary, that dictionary is
            used to provide the certificate information, with the
            top-level values being used as a fallback. <br />
            This method returns <code>YES</code> on success,
            <code>NO</code> on failure... if it returns
            <code>NO</code> then the receiver will <em>not</em>
            be capable of handling incoming web requests! <br />
            Typically a failure will be due to an invalid
            address or port being specified... a port may not
            already be in use and may not be in the range up to
            1024 (unless running as the super-user). <br /> Call
            this with a nil/empty port argument to shut the server
            down as soon as all current connections are closed
            (and refuse new incoming connections).
          </desc>
        </method>
        <method type="void">
          <sel>setConnectionTimeout:</sel>
          <arg type="NSTimeInterval">aDelay</arg>
          <desc>
            Sets the time after which an idle connection should be
            shut down. <br /> Default is 30.0
          </desc>
        </method>
        <method type="void">
          <sel>setDelegate:</sel>
          <arg type="id">anObject</arg>
          <desc>
            Sets the delegate object which processes requests for
            the receiver.
          </desc>
        </method>
        <method type="void">
          <sel>setDurationLogging:</sel>
          <arg type="BOOL">aFlag</arg>
          <desc>
            Sets a flag to determine whether logging of request
            and connection durations is to be performed. <br /> If
            this is <code>YES</code> then the duration of requests
            and connections will be logged using the
            <ref type="method" id="-webLog:for:" class="(WebServerDelegate)">[&lt;WebServerDelegate&gt;-webLog:for:]</ref> method. <br /> The request duration is calculated from the point where the first byte of data in the request is read to the point where the response has been completely written. <br /> This is useful for debugging and where a full audit trail is required.
          </desc>
        </method>
        <method type="void">
          <sel>setFoldHeaders:</sel>
          <arg type="BOOL">aFlag</arg>
          <desc>
            Sets a flag to determine whether the header lines in
            responses are folded if they are over 78
            characters (off by default). <br /> Some buggy
            clients don't support folding, but do accept
            <strong>long</strong> header lines, and this
            compatibility setting may be used to allow
            such clients to handle the server's responses (though
            this may of course break things for other clients).
            <br /> This setting applies to any connection
            established after the setting is changed.
            <br /> Because use of this setting could result in a
            faulty response (one with a <strong>long</strong>
            header) being sent to a client which correctly
            handles folded headers, it's also controllable
            individually for each response, so the same
            process can respond both to clients which expect
            folded headers and clients which expect
            <strong>long</strong> headers (see
            <ref type="method" id="-setFoldHeaders:" class="WebServerResponse">[WebServerResponse -setFoldHeaders:]</ref>).
          </desc>
        </method>
        <method type="void">
          <sel>setIOThreads:</sel>
          <arg type="NSUInteger">threads</arg>
          <sel>andPool:</sel>
          <arg type="NSInteger">poolSize</arg>
          <desc>
            Sets the number of <var>threads</var> used to process
            basic I/O and the size of the thread pool used by the
            receiver for handling parsing of incoming
            requests, generation of outgoing responses, and
            pre/post processing of requests by the delegate.
            <br /> This defaults to no use of <var>threads</var>
            . <br /> NB. Since each thread typically uses two file
            descriptors to handle any inter-thread message
            dispatch, enabling threading will use at least
            two extra file descriptors per thread... this may
            easily cause you to go beyound the per-process limit
            imposed by the operating system and you may wish to
            configure a smaller connection limit or tune the
            O/S to allow more descriptors.
          </desc>
        </method>
        <method type="void">
          <sel>setLogRawIO:</sel>
          <arg type="BOOL">aFlag</arg>
          <desc>
            Sets a flag to determine whether I/O logging is to be
            performed. <br /> If this is <code>YES</code>
            then all incoming requests and their responses will be
            logged using the
            <ref type="method" id="-webLog:for:" class="(WebServerDelegate)">[&lt;WebServerDelegate&gt;-webLog:for:]</ref> method.
          </desc>
        </method>
        <method type="void">
          <sel>setMaxBodySize:</sel>
          <arg type="NSUInteger">max</arg>
          <desc>
            Sets the maximum size of an uploaded request body.
            <br /> The default is 4M bytes. <br /> The HTTP
            failure response for too large a body is 413.
          </desc>
        </method>
        <method type="void">
          <sel>setMaxConnectionDuration:</sel>
          <arg type="NSTimeInterval">max</arg>
          <desc>
            Sets the maximum total duration of the incoming
            requests handled on an individual connection.
            After this many requests are handled, the connection
            is closed (so another client may get a chance to
            connect). <br /> The default is 10.0 seconds.
          </desc>
        </method>
        <method type="void">
          <sel>setMaxConnectionRequests:</sel>
          <arg type="NSUInteger">max</arg>
          <desc>
            Sets the maximum size number of incoming requests to
            be handled on an individual connection. After this many
            requests are handled, the connection is closed (so
            another client may get a chance to connect). <br />
            The default is 100 requests.
          </desc>
        </method>
        <method type="void">
          <sel>setMaxConnections:</sel>
          <arg type="NSUInteger">max</arg>
          <desc>
            Sets the maximum number of simultaneous connections
            with clients. <br /> The default is 128. <br /> A
            value of zero permits unlimited connections. <br />
            If this limit is reached, the behavior of the software
            depends upon the value set by the
            <ref type="method" id="-setMaxConnectionsReject:">
              -setMaxConnectionsReject:
            </ref>
            method.
          </desc>
        </method>
        <method type="void">
          <sel>setMaxConnectionsPerHost:</sel>
          <arg type="NSUInteger">max</arg>
          <desc>
            Sets the maximum number of simultaneous connections
            with a particular remote host. <br /> The default is
            32. <br /> A value of zero permits unlimited
            connections. <br /> If this value is greater
            than that of
            <ref type="method" id="-setMaxConnections:">
              -setMaxConnections:
            </ref>
            then it will have no effect as the maximum number of
            connections from one host cannot be reached.
            <br /> The HTTP failure response for too many
            connections from a host is 503.
          </desc>
        </method>
        <method type="void">
          <sel>setMaxConnectionsReject:</sel>
          <arg type="BOOL">reject</arg>
          <desc>
            <p>
              This setting (default value <code>NO</code>)
              determines the behavior of the software when
              the number of simultaneous incoming connections
              exceeds the value set by the
              <ref type="method" id="-setMaxConnections:">
                -setMaxConnections:
              </ref>
              method.
            </p>
            <p>
              If <var>reject</var> is <code>NO</code>, the software
              will simply not accept the incoming connections
              until some earlier connection is terminated, so the
              incoming connections will be queued by the
              operating system and may time-out if no
              connections become free quickly enough for
              them to be handled. In the case of a huge number of
              incoming connections the 'listen' queue of the
              operating system may fill up and connections
              may be lost altogether.
            </p>
            <p>
              If <var>reject</var> is yes, then the service will set
              aside a slot for one extra connection and, when the
              number of permitted connections is exceeded, the
              server will accept the first additional
              connection, send back an HTTP 503 response,
              and drop the additional connection again. This means
              that clients should receive a 503 response rather
              than finding that their connection attempts block
              and possible time out.
            </p>
          </desc>
        </method>
        <method type="void">
          <sel>setMaxKeepalives:</sel>
          <arg type="NSUInteger">max</arg>
          <desc>
            Sets the maximum number of connections in each I/O
            thread which are to be kept in a 'keepalive' state
            waiting for a new request once a request completes.
            <br /> The permitted range is currently from 1 to
            1000, with settings outside that range being treated
            as the default value (100).
          </desc>
        </method>
        <method type="void">
          <sel>setMaxRequestSize:</sel>
          <arg type="NSUInteger">max</arg>
          <desc>
            Sets the maximum size of an incoming request
            (including all headers, but not the body).
            <br /> The default is 8K bytes. <br /> The HTTP
            failure response for too large a request is 413.
          </desc>
        </method>
        <method type="void">
          <sel>setPermittedMethods:</sel>
          <arg type="NSSet*">s</arg>
          <desc>
            Sets the HTTP methods which may be used by the server.
            <br /> Any incoming request using a method not
            listed in the permitted set is rejected with an HTTP
            501 response. <br /> The default set contains only the
            GET and POST methods.
          </desc>
        </method>
        <method type="BOOL">
          <sel>setPort:</sel>
          <arg type="NSString*">aPort</arg>
          <sel>secure:</sel>
          <arg type="NSDictionary*">secure</arg>
          <desc>
            Deprecated... use
            <ref type="method" id="-setAddress:port:secure:">
              -setAddress:port:secure:
            </ref>
            instead.
          </desc>
        </method>
        <method type="void">
          <sel>setRoot:</sel>
          <arg type="NSString*">aPath</arg>
          <desc>
            Set root path for loading template files from. <br />
            Templates may only be loaded from within this
            directory.
          </desc>
        </method>
        <method type="void">
          <sel>setSecureProxy:</sel>
          <arg type="BOOL">aFlag</arg>
          <desc>
            Configures a flag to say whether the receiver is
            running behind a secure proxy and all connections
            are to be considered as having come in via https.
          </desc>
        </method>
        <method type="void">
          <sel>setSubstitutionLimit:</sel>
          <arg type="NSUInteger">depth</arg>
          <desc>
            Sets the maximum recursion <var>depth</var> allowed
            for substitutions into templates. This defaults to 4.
          </desc>
        </method>
        <method type="void">
          <sel>setUserInfo:</sel>
          <arg type="NSObject*">info</arg>
          <sel>forRequest:</sel>
          <arg type="WebServerRequest*">request</arg>
          <desc>
            Stores additional user information with a
            <var>request</var>. <br /> This information may be
            retrieved later using the
            <ref type="method" id="-userInfoForRequest:">
              -userInfoForRequest:
            </ref>
            method.
          </desc>
        </method>
        <method type="void">
          <sel>setVerbose:</sel>
          <arg type="BOOL">aFlag</arg>
          <desc>
            Sets a flag to determine whether verbose logging is to
            be performed. <br /> If this is <code>YES</code> then
            all incoming requests and their responses will be
            logged using the
            <ref type="method" id="-webLog:for:" class="(WebServerDelegate)">[&lt;WebServerDelegate&gt;-webLog:for:]</ref> method. <br /> Setting this to <code>YES</code> automatically sets duration logging to <code>YES</code> as well, though you can then call <ref type="method" id="-setDurationLogging:">-setDurationLogging:</ref> to set it back to <code>NO</code>. <br /> This is useful for debugging and where a full audit trail is required.
          </desc>
        </method>
        <method type="BOOL">
          <sel>streamData:</sel>
          <arg type="NSData*">data</arg>
          <sel>withResponse:</sel>
          <arg type="WebServerResponse*">response</arg>
          <desc>
            <p>
              This may only be called in the case where a call to
              the delegate's
              <ref type="method" id="-processRequest:response:for:" class="(WebServerDelegate)">[&lt;WebServerDelegate&gt;-processRequest:response:for:]</ref> method to process a request returned <code>NO</code>, indicating that the delegate would handle the request asynchronously and complete it later.
            </p>
            <p>
              In this case the <var>response</var> content should be
              empty, and instead of sending the
              <var>response</var> in one go the server will send
              the <var>response</var> header followed by the
              supplied <var>data</var>. Subsequent calls to
              this method using the same <var>response</var>
              object will send more <var>data</var> to the
              client. <br /> The code which calls this method
              <em>must</em> terminate the sequence of calls with a
              call to the
              <ref type="method" id="-completedWithResponse:">
                -completedWithResponse:
              </ref>
              method.
            </p>
            <p>
              The method returns <code>YES</code> is the
              <var>data</var> is scheduled for sending to the
              client, <code>NO</code> if the client has already
              dropped the connection and there is no point
              attempting to stream more <var>data</var>.
            </p>
          </desc>
        </method>
        <method type="BOOL">
          <sel>substituteFrom:</sel>
          <arg type="NSString*">aTemplate</arg>
          <sel>using:</sel>
          <arg type="NSDictionary*">map</arg>
          <sel>into:</sel>
          <arg type="NSMutableString*">result</arg>
          <sel>depth:</sel>
          <arg type="NSUInteger">depth</arg>
          <desc>
            Perform substitutions replacing the markup in
            <var>aTemplate</var> with the values supplied by
            <var>map</var> and appending the results to the
            <var>result</var>. <br /> Substitutions are
            recursive, and the <var>depth</var> argument is
            used to specify the current recursion <var>depth</var>
            (you should normally call this method with a
            <var>depth</var> of zero at the start of processing a
            template). <br /> Any value inside SGML comment
            delimiters ('&lt;!--' and '--&gt;') is treated
            as a possible key in <var>map</var> and the entire
            comment is replaced by the corresponding
            <var>map</var> value (unless it is <code>nil</code>).
            Recursive substitution is done unless the mapped
            value <em>starts</em> with an SGML comment. <br />
            While the <var>map</var> is nominally a dictionary,
            in fact it may be any object which responds to the
            objectForKey: method by returning an NSString
            or <code>nil</code>, you can therefore use it to
            dynamically replace tokens within a template
            page in an intelligent manner. <br /> The method
            returns <code>YES</code> on success,
            <code>NO</code> on failure (<var>depth</var> too
            great). <br /> You don't normally need to use this
            method directly... call the
            <ref type="method" id="-produceResponse:fromTemplate:using:">-produceResponse:fromTemplate:using:</ref> method instead.
          </desc>
        </method>
        <method type="NSObject*">
          <sel>userInfoForRequest:</sel>
          <arg type="WebServerRequest*">request</arg>
          <desc>
            Retrieves additional user information (previously
            set using the
            <ref type="method" id="-setUserInfo:forRequest:">
              -setUserInfo:forRequest:
            </ref>
            method) from a <var>request</var>.
          </desc>
        </method>
      </class>
    </chapter>
    <chapter>
      <heading>
        Software documentation for the WebServerRequest class
      </heading>
      <class name="WebServerRequest" super="GSMimeDocument">
        <declared>WebServer.h</declared>
        <desc>
          Do not attempt to subclass the WebServerRequest class to
          add instance variables... the public interface is
          intended to keep your compiler happy, but does not
          guarantee that the instance variable layout is
          actually what it seems.
        </desc>
      </class>
    </chapter>
    <chapter>
      <heading>
        Software documentation for the WebServerResponse class
      </heading>
      <class name="WebServerResponse" super="GSMimeDocument">
        <declared>WebServer.h</declared>
        <desc>
          Do not attempt to subclass the WebServerResponse class to
          add instance variables... the public interface is
          intended to keep your compiler happy, but does not
          guarantee that the instance variable layout is
          actually what it seems.
        </desc>
        <method type="void">
          <sel>setFoldHeaders:</sel>
          <arg type="BOOL">aFlag</arg>
          <desc>
            Behaves as
            <ref type="method" id="-setFoldHeaders:" class="WebServer">[WebServer -setFoldHeaders:]</ref> but applies only to the headers in the receiver.
          </desc>
        </method>
      </class>
    </chapter>
    <chapter>
      <heading>
        Software documentation for the
        NSObject(WebServerDelegate)
        informal protocol
      </heading>
      <category name="WebServerDelegate" class="NSObject">
        <declared>WebServer.h</declared>
        <desc>
          This is an informal protocol documenting optional
          methods which will be used if implemented by the
          delegate.
        </desc>
        <method type="uint32_t">
          <sel>incrementalRequest:</sel>
          <arg type="WebServerRequest*">request</arg>
          <sel>for:</sel>
          <arg type="WebServer*">http</arg>
          <desc>
            <em>Description forthcoming.</em>
          </desc>
        </method>
        <method type="void">
          <sel>postProcessRequest:</sel>
          <arg type="WebServerRequest*">request</arg>
          <sel>response:</sel>
          <arg type="WebServerResponse*">response</arg>
          <sel>for:</sel>
          <arg type="WebServer*">http</arg>
          <desc>
            If your delegate implements this method, it will be
            called by the
            <ref type="method" id="-completedWithResponse:">
              -completedWithResponse:
            </ref>
            method before the <var>response</var> data is
            actually written to the client. <br /> This method
            may re-write the <var>response</var>, changing the
            result of the earlier methods. <br /> You may use
            the
            <ref type="method" id="-userInfoForRequest:" class="WebServer">[WebServer -userInfoForRequest:]</ref> method to obtain any information passed from an earlier stage of processing. <br /> NB. if threading is turned on this method may be called from a thread other than the master one.
          </desc>
        </method>
        <method type="BOOL">
          <sel>preProcessRequest:</sel>
          <arg type="WebServerRequest*">request</arg>
          <sel>response:</sel>
          <arg type="WebServerResponse*">response</arg>
          <sel>for:</sel>
          <arg type="WebServer*">http</arg>
          <desc>
            If your delegate implements this method, it will be
            called before the
            <ref type="method" id="-processRequest:response:for:" class="(WebServerDelegate)">[&lt;WebServerDelegate&gt;-processRequest:response:for:]</ref> method and with the same parameters. <br /> If this method returns <code>YES</code>, then it is assumed to have completed the processing of the <var>request</var> and the main <ref type="method" id="-processRequest:response:for:" class="(WebServerDelegate)">[&lt;WebServerDelegate&gt;-processRequest:response:for:]</ref> method is not called. Otherwise processing continues as normal. <br /> You may use the <ref type="method" id="-setUserInfo:forRequest:" class="WebServer">[WebServer -setUserInfo:forRequest:]</ref> method to pass information to the <ref type="method" id="-processRequest:response:for:" class="(WebServerDelegate)">[&lt;WebServerDelegate&gt;-processRequest:response:for:]</ref> and/or <ref type="method" id="-postProcessRequest:response:for:">-postProcessRequest:response:for:</ref> methods. <br /> NB. This method is called <em>before</em> any HTTP basic authentication is done, and may (if threading is turned on) be called from a thread other than the master one.
          </desc>
        </method>
        <method type="void">
          <sel>webAlert:</sel>
          <arg type="NSString*">message</arg>
          <sel>for:</sel>
          <arg type="WebServer*">http</arg>
          <desc>
            Log an error or warning... if the delegate does not
            implement this method, the <var>message</var> is
            logged to stderr using the NSLog function.
          </desc>
        </method>
        <method type="void">
          <sel>webAudit:</sel>
          <arg type="NSString*">message</arg>
          <sel>for:</sel>
          <arg type="WebServer*">http</arg>
          <desc>
            Log an audit record... if the delegate does not
            implement this method, the <var>message</var> is
            logged to stderr. <br /> The logged record is
            similar to the Apache common log format, though it
            differs after the timestamp:
            <deflist>
              <term>ip address</term>
              <desc>
                the address of the client host making the request
              </desc>
              <term>ident</term>
              <desc>
                not currently implemented... '-' as placeholder
              </desc>
              <term>ident</term>
              <desc>
                not currently implemented... '-' as placeholder
              </desc>
              <term>user</term>
              <desc>
                the remote user name from the authorization header,
                or '-'
              </desc>
              <term>timestamp</term>
              <desc>
                the date/time enclosed in square brackets
              </desc>
              <term>command</term>
              <desc>
                The command sent in the request... as a quoted
                string
              </desc>
              <term>agent</term>
              <desc>
                The user-agent header from the request... as a
                quoted string
              </desc>
              <term>result</term>
              <desc>
                The initial response line... as a quoted string
              </desc>
            </deflist>
          </desc>
        </method>
        <method type="void">
          <sel>webLog:</sel>
          <arg type="NSString*">message</arg>
          <sel>for:</sel>
          <arg type="WebServer*">http</arg>
          <desc>
            Log a debug... if the delegate does not implement this
            method, no logging is done.
          </desc>
        </method>
      </category>
    </chapter>
    <chapter>
      <heading>
        Software documentation for the WebServerDelegate
        protocol
      </heading>
      <protocol name="WebServerDelegate">
        <declared>WebServer.h</declared>
        <desc>
          This protocol is implemented by a delegate of a
          WebServer instance in order to allow the delegate
          to process requests which arrive at the server.
        </desc>
        <method type="BOOL">
          <sel>processRequest:</sel>
          <arg type="WebServerRequest*">request</arg>
          <sel>response:</sel>
          <arg type="WebServerResponse*">response</arg>
          <sel>for:</sel>
          <arg type="WebServer*">http</arg>
          <desc>
            Process the HTTP <var>request</var> whose headers
            and data are provided in a GSMimeDocument subclass.
            <br /> Extra headers are created as follows -
            <deflist>
              <term>x-http-method</term>
              <desc>
                The method from the HTTP <var>request</var> (eg.
                GET or POST)
              </desc>
              <term>x-http-path</term>
              <desc>
                The path from the HTTP <var>request</var>, or an
                empty string if there was no path.
              </desc>
              <term>x-http-query</term>
              <desc>
                The query string from the HTTP <var>request</var>
                or an empty string if there was no query.
              </desc>
              <term>x-http-scheme</term>
              <desc>
                Returns the URL scheme used (<var>http</var> or
                https) to access the server. This is https if
                the <var>request</var> arrived on an encrypted
                connection or if the server is configured as
                being behind a secure proxy.
              </desc>
              <term>x-http-version</term>
              <desc>
                The version from the HTTP <var>request</var>.
              </desc>
              <term>x-local-address</term>
              <desc>
                The IP address of the local host receiving the
                <var>request</var>.
              </desc>
              <term>x-local-port</term>
              <desc>
                The port of the local host receiving the
                <var>request</var>.
              </desc>
              <term>x-remote-address</term>
              <desc>
                The IP address of the host that the
                <var>request</var> came from.
              </desc>
              <term>x-remote-port</term>
              <desc>
                The port of the host that the <var>request</var>
                came from.
              </desc>
              <term>x-http-username</term>
              <desc>
                The username from the 'authorization' header if the
                <var>request</var> supplied HTTP basic
                authentication.
              </desc>
              <term>x-http-password</term>
              <desc>
                The password from the 'authorization' header if the
                <var>request</var> supplied HTTP basic
                authentication.
              </desc>
              <term>x-count-requests</term>
              <desc>
                The number of requests being processed at the point
                when this <var>request</var> started (includes
                this <var>request</var>).
              </desc>
              <term>x-count-connections</term>
              <desc>
                The number of connections established to the
                WebServer at the point when this
                <var>request</var> started (including the
                connection this <var>request</var> arrived
                on).
              </desc>
              <term>x-count-connected-hosts</term>
              <desc>
                The number of connected hosts (IP addresses) at the
                point when this <var>request</var> started
                (including the host which sent this
                <var>request</var>).
              </desc>
              <term>x-count-host-connections</term>
              <desc>
                The number of connections to the web server from
                the host which sent this <var>request</var> at the
                point when this <var>request</var> started
                (includes the connection that this
                <var>request</var> arrived on).
              </desc>
            </deflist>
            On completion, the method must modify
            <var>response</var> (an instance of a subclass of
            GSMimeDocument) to contain the data and
            headers to be sent out. <br /> The 'content-length'
            header need not be set in the <var>response</var> as
            it will be overridden anyway. <br /> The special 'HTTP'
            header will be used as the response/status line. If
            not supplied, 'HTTP/1.1 200 Success' or 'HTTP/1.1 204
            No Content' will be used as the <var>response</var>
            line, depending on whether the data is empty or not.
            <br /> If an exception is raised by this method, the
            <var>response</var> produced will be set to 'HTTP/1.0
            500 Internal Server Error' and the connection will be
            closed. <br /> If the method returns
            <code>YES</code>, the WebServer instance sends the
            <var>response</var> to the client process which made
            the <var>request</var>. <br /> If the method returns
            <code>NO</code>, the WebServer instance assumes that
            the delegate is processing the <var>request</var>
            asynchronously, either in another thread or
            with completion being triggered by an asynchronous I/O
            event. The server takes no action respond to the
            <var>request</var> until the delegate calls
            <ref type="method" id="-completedWithResponse:" class="WebServer">[WebServer -completedWithResponse:]</ref> to let it know that processing is complete and the <var>response</var> should at last be sent out. <br /> This method is always called in the master thread of your WebServer instance (usually the main thread of your application).
          </desc>
        </method>
      </protocol>
    </chapter>
  </body>
</gsdoc>
