UCW

The RERL Protocol 

A UCW server sits in a tight loop waiting for incoming HTTP requests, elaborating them and then sending out the HTTP responses. This loop is called the "RERL" (Request-Eval-Response Loop) and the objects, methods are variables involved is the RERL are described here.

Components 

(defgeneric (setf component.calling-component) (caller component))
(defgeneric component.continuation (component)
  (:documentation "Accessor for COMPONENT's continuation.

The continuation is implemented as a 1 arg lambda which is called
with the value COMPONENT answers. and continues whatever was
stopped when control was transfered to the component."))
(defgeneric (setf component.continuation) (k component))
(defgeneric call-component (caller callee)
  (:documentation "Transfer control from the component CALLER, to
  the component CALLEE.

CALLEE should replace CALLER in the user interface (by setting
itself in CALLER's place). CALLEE can return control to CALLER by
calling answer-component.

call-component can be called by user code even though it will
generally be called through the CALL macro."))
(defgeneric call-request-path (component)
  (:documentation "Return current request path as a list for reporting."))
(defgeneric answer-component  (callee value)
  (:documentation "Return control to CALLEE's CALLER, continuing
  with the value VALUE.

answer-component can be called by user code though it will
generally be called through the ANSWER macro."))
(defgeneric parent (component)
  (:documentation "Returns the parent of COMPONENT.

Only window components and detached components may return NIL
from this function."))
(defgeneric inspectable-component (component)
  (:documentation "Returns T when inspector links should be
  created for this component.

If methods on this function need a default value (iow the user
hasn't explicitly specified a preference) the return value of the
generic function INSPECT-COMPONENTS (passed the current
application) should be used."))

The rendering protocol 

(defgeneric render (component)
  (:documentation "The generic entry point for rendering
  components to the user.")
  (:method-combination wrapping-standard))
(defgeneric compute-url (component &key action-id)
  (:documentation "Return a URL with the proper session, frame
  and action-id parameters."))
(defgeneric update-url (component url)
  (:documentation "Prepare URL for rendering as action urls.

Each component can define a method on UPDATE-URL to add
component-specific parameters. This is generally coupled with an
entry-point to create bookmark-able urls."))

Servers 

(defgeneric server.applications (server)
  (:documentation "Return a list of all the application objects
  SERVER manages."))
(defgeneric startup-server (server)
  (:documentation "Make SERVER start responding to requests."))
(defgeneric shutdown-server (server)
  (:documentation "Make SERVER stop responding to requests and
  close/release and resources."))
(defgeneric associated-application (server request)
  (:documentation "Return the application object which will
  handle REQUEST."))
(defgeneric handle-request (server request response)
  (:documentation "Perform one iteration of the RERL on REQUEST and RESPONSE.

Methods defined on this generic function must be built from the
methods associated-application and service and should, as much as
possible, handle all conditions signalled by calls to service."))

Applications 

(defgeneric application.url-prefix (application)
  (:documentation "Returns the url prefix (a string) for APPLICATION.

The URL prefix is that string which, when used as the prefix of
an incoming http query path, identifies an application."))
(defgeneric make-request-context (application request response)
  (:documentation "Create a new request-context form REQUEST and RESPONSE.

The returned context will have its application, request and
response slots set to APPLICATION, REQUEST and RESPONSE.

This method need not neccessarily return a new object each time
but may reuse previouly created objects in which case a call to
clear-context must be made before returning the object."))
(defgeneric find-session (application context)
  (:documentation "Return the session object in CONTEXT or NIL if
  there's no session."))
(defgeneric make-new-session (application)
  (:documentation "Return a new session object."))
(defgeneric find-entry-point (application context)
  (:documentation "Returns the entry-point object for CONTEXT's request.

If no such entry-point exists return NIL."))
(defgeneric remove-expired-sessions (application)
  (:documentation "Remove all the expired sessions in APPLICATION.

Implementations of this method must use the generic function
EXPIREDP to determine if a session is expired or not, and must
call DELETE-SESSION on the session objects."))
(defgeneric delete-session (application session &optional expire)
  (:documentation "Remove the session SESSION from APPLICATION.

If EXPIRE is T then EXPIRE-SESSION MUST be called on the
session."))
(defgeneric startup-application (application)
  (:documentation "Start the application's request-eval-response loop."))
(defgeneric shutdown-application (application)
  (:documentation "Terminate the application's life cycle.

Release any and all resources held by APPLICATION. The value
returned by the generic function is unspecified."))
(defgeneric debug-on-error (application)
  (:documentation "Returns T if APPLICATION should attempt to
  debug errors (instead of just returning an error page)."))

Request Contexts 

(defgeneric context.request (context)
  (:documentation "Accessor for the request object in CONTEXT."))
(defgeneric (setf context.request) (request context))
(defgeneric context.response (context)
  (:documentation "Accessor for the response object in CONTEXT."))
(defgeneric (setf context.response) (response context))
(defgeneric context.application (context)
  (:documentation "Accessor for the application object in CONTEXT."))
(defgeneric (setf context.application) (application context))
(defgeneric context.session (context)
  (:documentation "Accessor for the session object in CONTEXT."))
(defgeneric (setf context.session) (session context))
(defgeneric context.current-frame (context)
  (:documentation "Return the \"current\" (most recent)
  session-frame in CONTEXT's session.")
  (:method ((context request-context))
    "Simply call session.current-frame on context's session object."
    (session.current-frame (context.session context))))
(defgeneric context.window-component (context)
  (:documentation "Return the \"current\" (most recenct) window
  component in CONTEXT's session."))
(defgeneric (setf context.window-component) (component context))
(defgeneric call-callbacks (context)
  (:documentation "Call all the request callbacks in CONTEXT's request.

Methods defined on this generic function must be built up from
calls to map-parameters (part of the backend protocol) and
call-callback."))
(defgeneric find-session-id (context)
  (:documentation "Returns the client supplied session-id in CONTEXT.

Methods should inspect the context's request object and return a
string specifying the session-id. No guarantee on the
validity (well-formedness or existence) of the returned
session-id is made.

If no session-id is supplied NIL must be returned."))
(defgeneric find-frame-id (context)
  (:documentation "Same as find-session-id but looks for the frame id."))
(defgeneric find-action-id (context)
  (:documentation "Same as find-action-id but looks for the action id."))
(defgeneric clear-context (context)
  (:documentation "Prepare REQUEST-CONTEXT for re-use.

This method must destructivly modify CONTEXT so that it becomes
indistinguishable from a freshly created object as returned by
make-request-context."))

The generic function SERVICE  

Service method and various constants and variables used while serving a request.

(defgeneric service (relevant-object context)
  (:documentation "The core request handling generic function.

The service protocol consists of 4 passes: application -> session
-> session-frame -> action. At each phase the appropriate object
is passed to service with the current request object (which is
also bound to *context*). The appropiate object must perform
whatever it needs and then explicitly call service again passing
it the next object in the chain."))

Sessions 

(defgeneric session.id (session)
  (:documentation "Returns the id of SESSION.

An ID is a unique (within the same application) object
identifying SESSION."))
(defgeneric expiredp (session)
  (:documentation "Returns true if SESSION has expired."))
(defgeneric expire-session (session)
  (:documentation "Causes this session to cease to exist."))
(defgeneric make-new-frame (session)
  (:documentation "Adds a new session-frame object to SESSION."))
(defgeneric session.current-frame (session)
  (:documentation "Return the current active frame in the session."))
(defgeneric session.value (key session &optional default)
  (:documentation "Fetch the value with key KEY in the session SESSION.

DEFAULT is returned should KEY not be found in SESSION's
session-table.

Keys are compared using EQL."))
(defgeneric (setf session.value) (value key session &optional default)
  (:documentation "Sets the value of KEY in SESSION to VALUE.

The DEFAULT argument is required to maintain the gethash-ish
interface and to allow for the use of this function in incf and
push macros.

As with session.value keys are compared with EQL."))

Session Frames 

(defgeneric frame.id (session-frame))
(defgeneric frame.window-component (session-frame)
  (:documentation "Accessor for SESSION-FRAME's window component."))
(defgeneric (setf frame.window-component) (component session-frame))
(defgeneric call-callback (session-frame param-name value)
  (:documentation "Call the parameter callback in SESSION-FRAME
with name PARAM-NAME passing it VALUE. PARAM-NAME is always a
string, VALUE is either a string or a list of strings depending
on how many values where under the name PARAM-NAME."))
(defgeneric find-action (session-frame action-id)
  (:documentation "Return the action (a function) associated with ACTION-ID."))
(defgeneric make-next-frame (frame new-frame-id)
  (:documentation "Create the \"next\" frame object with id NEW-FRAME-ID.

The new frame object must build its history (component,
backtracks, etc.) assuming that FRAME is the previous (in
chronological order) frame."))

Entry Points 

NB: actions are just regular methods and so don't explicitly appear in this protocol.

(defgeneric register-entry-point (entity entry-point)
  (:documentation "Inform ENTITY (either an application, a server
  or a backend) to start handling requests for ENTRY-POINT."))
(defgeneric unregister-entry-point (entity entry-point)
  (:documentation "Inform ENTITY (either an application, a server
  or a backend) to stop handling requests for ENTRY-POINT."))
(defgeneric entry-point.url (entry-point)
  (:documentation "Returns the query path associated with ENTRY-POINT.

The returned query-path will need to be combined with the
application's url-prefix to produce a complete query-path."))
(defgeneric entry-point.action (entry-point)
  (:documentation "Returns the function which should handle
  requests for the entry point."))
(defgeneric entry-point.application (entry-point)
  (:documentation "Returns the application (which may be NIL) for
  this entry point."))

The Backend 

UCW extracts the particular web server sude through this protocol.

(defgeneric initialize-backend (backend &rest init-args)
  (:documentation "Prepare BACKEND but do not actually start serving request."))
(defgeneric startup-backend (backend &rest startup-args)
  (:documentation "Start the RERL. This method may block on
  single threaded lisps."))
(defgeneric shutdown-backend (backend &rest shutdown-args)
  (:documentation "Stop the RERL and release any resources."))
(defgeneric publish-directory (backend directory-pathname url-base)
  (:documentation "Publish the directory at PATHNAME at the URLs starting from URL-BASE."))
(defgeneric get-header (message header-name)
  (:documentation "Return the value of the header named HEADER-NAME.

HEADER-NAME must be a string and will be compared case sensitvly
agaist the headers in the message.

Callers are not allowed to modify the value returned by
GET-HEADER."))
(defgeneric (setf get-header) (value message header-name)
  (:documentation "Change the value of the header named
  HEADER-NAME. Like in get-header HEADER-NAME must be a
  string."))
(defgeneric add-header (message header-name value)
  (:documentation "Add another header line with
  HEADER-NAME=VALUE. Returns VALUE.

Like get-header and (setf get-header) HEADER-NAME must be a
string."))
(defgeneric shutdown (message))
(defgeneric query-path (request))
(defgeneric get-parameter (request parameter-name)
  (:documentation "Returns the query value, a string or a list of
  strings, associated with the name PARAMETER-NAME. As with
  GET-HEADER callers are not allowed to modify the value retruned
  by this function."))
(defgeneric map-parameters (request lambda)
  (:documentation "Apply LAMBDA to all the parameters in REQUEST.

LAMBDA will be passed two arguments: the name of the parameter, a
string, and the value of the parameter, a string or a list of
strings. The values are passed in that order and LAMBDA must not
modify any of the values passed to it."))
(defgeneric content-stream (response)
  (:documentation "Return the stream we can write html output
  to."))
(defgeneric clear-response (response)
  (:documentation "Restore RESPONSE to its clean state.

This generic function is generally used when dealing with an
error which occurs during the rendering of a window."))