Copyright © 1998 W3C (MIT, INRIA, Keio ), All Rights Reserved. W3C liability, trademark, document use and software licensing rules apply.
This draft specification is a work in progress representing the current consensus of the W3C HTTP-NG Protocol Design Group. This is a W3C Working Draft for review by W3C members and other interested parties. Publication as a working draft does not imply endorsement by the W3C membership.
This draft document describes an initial set of extensible formal object interfaces that allow some of the basic functionality of HTTP to be captured in the HTTP-NG framework. The draft is a result of the HTTP-NG project at the W3C and is part of a suite of documents describing the HTTP-NG design and prototype implementation:
Please send comments on this specification to <www-http-ng-comments@w3.org>.
Part of the charter of the Protocol Design Group of the HTTP-NG project is to identify a set of formal interfaces that will allow the current functionality of the Web to be captured, as well as support future needs. Before delving into the specific interfaces, the kinds of concepts involved need to be described. The actual interface descriptions here are cast in terms of distributed object systems, the merits of which as a foundation for the Web have been discussed in "Migrating the Web toward Distributed Objects" and elsewhere. The intent is not to imply that what is presented here is complete or final, but rather to provide a starting point for how the Web should look in the future.
When we think of the Web today, the idea of a 'resource' comes to mind. In general, a resource is an Object that has some methods (e.g. in HTTP, Get Head and Post) that can be invoked on it. Objects may be stateful in that they have some sort of opaque 'native data' that influences their behavior. The nature of this native data is unknown to the outside, unless the object explicitly makes it known somehow. [Any stateful object may or may not have some means by which it stores persistent state across activations, but that's not really part of our concern here.]
Objects which are Renderable may be asked to produce a Rendering based on a set of Preferences. This is analogous to HTTP Get. A Rendering is a transformation of the object's native data into some other form, typically a collection of bytes with an interpretation determined by a named type relative to some typespace. Common examples are illustrated by the various MIME types, e.g. text/html Rendering for viewing in a web browser, and an application/postscript Rendering for printing. When a Renderable object is asked for a Rendering of a preferred type, the implementation of the object's method for this operation transforms or maps the native data to this Rendering type. Note that this transformation may or may not be reversible. If the Rendering format happens to be the same as the native data of the document, the transformation might be identity. Objects that have no native data themselves may be able to produce a Rendering by generating it from other sources (e.g. real world state, other objects).
A Rendering may be retrieved in one of two ways. Either the Rendering is returned as a value from a synchronous call, or the Rendering is requested and then sent asynchronously, in chunks, back to some RenderingSink. The former can be thought of as a 'client-pull' technique, and the latter as a 'server-push' technique. The sink approach is to support the notion of a 'stream', to deal with Renderings that are impractically large (e.g. images), or not well bounded (e.g. live video or audio).
Renderings may also be produced by an object acting as a FormProcessor . This is analogous to HTTP Post. In this case, instead of receiving information about RenderingPreferences, the object receives a set of Name/Value pairs that are interpreted in an implementation-specific manner to produce a Rendering.
Some objects may be asked to accept a Rendering. This is analogous to HTTP Put. The intent here is that of updating the object's native data. When such a request is made on an object, if the supplied rendering is transformable by the implementation into the native data, and such an operation is semantically permissible, the rendering is transformed into the native form. If it's not possible to transform the rendering into native form (e.g. supplying GIF to an object whose implementation doesn't know how to OCR an image to translate it to an internal text representation), then an exception needs to be raised. Note that some objects could actually have multiple native data forms internally, but this is generally unknown outside the object.
Objects may have a PropertySet. These are groups of attributes that are not normally part of the native data itself, but rather more descriptive of the object as a whole. This is often referred to as Meta-Data, and may include such information as author, version, summary, etc. Properties may be static or computed [an implementation detail].
In actual implementations, the data exchanges that take place during of method invocations may pass through one or more intermediate caches. Caches often maintain a copy of some object's Rendering to improve the speed with which a Rendering can be retrieved. What can be cached and what cannot is dependent on the operation semantics, the security policies of the parties involved, contractual obligations, and other concerns. CacheControl information must accompany each request and response where the potential for caching is of concern.
The previous section attempted to expose some general concepts, or 'types' that objects may be. The key word here is may. For example, not all objects need to be Renderable, not all need to be able to process forms, and some things simply have no interesting properties to expose. What's needed is the ability to describe each of these types in isolation, and be able to combine then as needed for particular circumstances. So for example, we want to define a Renderable type to be an object that has a set of operations or Methods dealing with the retrieval of a rendering. Similarly, we define a PropertySet type for those objects that need to have that sort of functionality, and so on.
In object oriented systems, bits of functionality are combined through inheritance. To say that something 'C' inherits from 'A' and 'B', means that C objects are a derived type, and can be used as a method parameter wherever an A, B, or C is required. C also provides the methods defined for A and B objects, in addition to any that may be defined specifically for C objects. These properties are transitive with respect to inheritance. So then, using the inheritance capabilities of the distributed object system, we can define new kinds of objects that are a number of these types (and hence implement their Methods) through inheritance.
For example, to capture the functionality of a WebDocument as we think of it today, we define WebDocument as an object that inherits Renderable (supporting the equivalent of HTTP's Get), and inherits from the PropertySet object (to primarily support independent retrieval of what is currently covered by some HTTP headers).
It is also using the mechanism of inheritance that types can be extended. Note that the previous description mentioned that a type C inheriting from A and B can define its own methods in addition to the ones inherited from its parents.
For example, A WebDocument can implement its own method that allows both Rendering and Properties to be retrieved in a single call. Another example could be a new object type, MicrowaveOven, that not only is Renderable (can supply an image of what's cooking), but also adds methods to turn it on and off. Printers and Scanners could be defined as children of a WebDocument, and a Copier as a child of those. The following figure is illustrative of this sort of type evolution.
This section attempts to basically describe how the components of the Web as we know them today could be cast using distributed objects with the kinds of interfaces described above, and illustrates some scenarios that would be difficult to implement with today's approach. In the descriptions, the word ObjRef is used to mean an object reference. This may either be something like a HTTP URL as we commonly see today, or it may be of a more general form that includes information about the object attributes (e.g. its type), in addition to the contact and instance identification information.
Given an ObjRef, a browser would like to contact the entity it refers to in order to receive a Rendering. If the ObjRef has the HTTP scheme, an assumption is made that the entity is a resource as we know it today and we treat it as we commonly would using HTTP1.x. [1]
If however the ObjRef has more information, (e.g. what object type it represents), the browser may take quite a different set of actions. Let's say it indicates that it's a 'WebDocument' type. The browser asks the document for a Rendering and its Properties, perhaps in a particular format. The WebDocument object receives the rendering request. It has its own implementation of the request, so how it actually processes the request may be different from other WebDocuments -- remember we're defining types here, and their intended semantics, not their actual implementations. [For example, its implementation might examine the request, and see that the requested Rendering content type is not available through local transformations of native data. It could call out to a Rendering transformation service (e.g. postscript to gif) to get the appropriate Rendering.] In the response to the browser, the WebDocument sends the Rendering, along with a set of Properties describing the document. The browser for example might notice that the document author is on the list of 'interesting people' that the browser's user has specified. The browser then decides to automatically add this ObjRef to the user's 'Favorites' folder.
In a future scenario, the browser might discover that the WebDocument had been extended with Daemon interfaces. A Daemon is basically an interface that accepts condition action pairs, and performs the action when the condition is true, typically the sending of some Event containing data to a Sink. Now, since this WebDocument's author is a user favorite, the browser decides that it would like to be notified of changes in the document so that the Rendering can be updated accordingly. It adds a Daemon (through the Daemon Interface that had been 'mixed in' with the WebDocument) to the WebDocument, whose Condition is true when the Document changes. The Daemon contains an Action that accepts Condition Results and an Event Sink (that the browser implements). This Action gets the new Rendering for the Document, packages it up in an Event and sends it to the browser's Event Sink. When the browser receives the Event, it knows that the Rendering should be updated. This might even be allowed to proceed in the background so that the browser's cache can be kept up to date. When the page is left, or when the cache entry gets dumped from the cache, the browser retracts its previously posted condition action pair from the WebDocument's Daemon interface.
If the browser sees a form method as one might today, e.g.
FORM METHOD="POST" ACTION="/cgi/wwwwais.cgi";
it treats the form just as it does today. If however, it saw a method that wasn't POST, e.g. ProcessForm, and the ACTION that wasn't the HTTP schemed URL but rather one indicating a FormProcessor object, it would invoke the named method on the specified object, passing the form parameters to the method as a property-list (a list of name-value pairs). Note here that the values in this list can be more than simple strings - any type may be passed, enabling a much richer and more compact set of inputs.
This section contains brief descriptions of interfaces that embody the concepts mentioned previously. Actual interfaces described in ILU's Interface Specification Language (ISL) can be found in the appendix. These interfaces are certain to evolve as missing and extraneous functionality is discovered through both review and prototype implementation.
This interface defines a number of basic types such as strings, times, intervals, etc., as well as the NgObject object type which forms a root class from which all NG classes inherit. This is useful to be able to provide all derived objects with a standard set of methods, as well as provide a type which may be used as a handle for any kind of NG-Object. A single method, GetInterfaceDefinitionSource, which provides a means for interface discovery, is declared.
In addition, some exceptions are defined in NgBasic. Certain operations, typically Get or Put style, may return a WouldBlock exception when the operation would block for some reason. Similarly, Conflict exceptions may be returned when the operation is somehow in conflict with another operation (perhaps simultaneous Puts on a Rendering) or operational semantics (perhaps a Put based on an old version as determined through e-tag information for example). The value optionally contained in the ExceptionInformation's Pickle is operation specific. For a WouldBlock, it could contain locking information for example. Those knowledgeable about locking could attempt to extract and make use of the lock information contained in the pickle. Those not knowledgeable about locking could just disregard the value, but still have knowledge that something is currently going on with the target object that would cause them to block waiting for a result.
There may be situations where an implementation might quickly reify an object in an object creation function and later determine that this object really doesn't exist. Since this sort of 'system exception' information isn't necessarily sent across the wire, a user exception, ObjectNotExist, is defined for this sort of event.
An object having methods intended for the asynchronous receipt of data (streaming data for example) is called a DataSink. The DataSink object type is 'abstract', in that it is meant to be subtyped, never directly instantiated. Subtypes will supply methods that are specialized to the particular type of data the the sink accepts. It methods are:
DataSinks may have a need to exert some control over the source side. The DataSource object type may be passed to a DataSink, and the DataSink can then invoke a number of 'flow-control' related methods:
Note that the methods on DataSink and DataSource are asynchronous. This avoids the return-trip time that synchronous call have. Since the states of these objects are influenced by the order in which methods are processed, these calls must take place over a communication channel that ensures that methods are processed in the order in which they are sent.
The object type WebDocument is primarily a combination of the Renderable and PropertySet object types, and is meant to be an NG analog to what Web documents are today. [2] The main method is GetRenderingandProperties, which is simply intended to be a combination of the GetRendering and GetProperties methods of its parents. This method mimics what we current have with HTTP Get. SendRenderingAndProperties and SendRenderingAndPropertiesSynched is similar only it allows for the return results to be sent asynchronously back to a RenderingAndPropertiesSink. The PutableWebDocument object type inherits from WebDocument, PutableRendering, and PutablePropertySet, and provides the analog to the HTTP 1.1 Put operation.
Rendering preferences are described through use of a RenderingPreferences record. The members of this record are briefly:
Renderings themselves are described through use of a Rendering record. The members of this record are briefly:
An object of type Renderable is able to produce a Rendering of the object. Examples are a text description, a graphic, an html page, an audio, etc. This first is Renderable itself. This type has a number of methods.
The PutableRendering object type provides the analog to the HTTP 1.1 Put operation. It adds a single method:
An object of type RenderingSink is able to asynchronously receive renderings. It inherits the RegisterSourceControl and Done methods from DataSink, and add several methods:
An object of type PropertySet has a method GetProperties used to retrieve name/value pairs, e.g. Authors, CreationTime, etc. A subtype of PropertySet, PutablePropertySet has a method PutProperties used to write name/value pairs.
An object of type FormProcessor is able to process Form based input, and produce an appropriate rendering as a response. This type has two methods:
Records are defined that may be sent along with requests and responses to provide caches and proxy relevant information. This mostly mimics the cache-related headers and Cache-Control header values found in HTTP 1.1. See the HTTP1.1 specification for the semantics. An issue that needs further thought is the crosscutting of cache-relevant information through multiple arguments - version information is a prime example.
This interface simply contains types for identifying character sets.
[1] The paper "Migrating the Web toward Distributed Objects", describes how in the distributed object system ILU, Get, Head and Post methods on an object can be invoked through existing HTTP through inheritance of the iluhttp.Resource object type. Through inheritance of this type, HTTP-NG style Web objects can interoperate with existing Web browser and servers, providing a migration path to the new technology.
[2] An implementer might chose to create a new type derived from both WebDocument, and from iluhttp.Resource (part of the ILU distribution), so that it can also interact with existing Web clients and servers.
(* ************************************************************************ *)
(*
Version 1.3 ISL for HTTP-NG, Dan Larner, 3-19-98
This work is very preliminary - Comments welcomed and encouraged!
'xxx' marks areas where thought is definitly needed
Please send comments, suggestions, contributions, etc. to the http-ng
mailing list, w3c-http-ng@w3.org and/or to larner@parc.xerox.com.
*)
(* ************************************************************************ *)
(* *************************** Basic Types ******************************** *)
(* ************************************************************************ *)
(* Defines a number of basic types used throughout HTTP-NG interfaces. *)
Interface NgBasic Brand "NG" ;
(* ********************** String & Type related *************************** *)
Type String = Sequence Of Short Character;
Type OptionalString = Optional String;
Type StringSequence = Sequence Of String;
Type ByteSequence = Sequence Of Byte;
Type URI = String; (* see RFC1738 and RFC 1808 *)
Type OptionalURI = Optional URI;
Type URISequence = Sequence Of URI;
Type OptionalCardinal = Optional Cardinal;
(* ************************************************************************ *)
(* **************************** Time Related ****************************** *)
(* Represents a number of microseconds elapsed since midnight
(00:00:00), January 1, 1970, coordinated universal time.
Note that negative values indicate number of microseconds
prior to the origin. *)
Type AbsoluteTime = Long Integer;
Type OptionalAbsoluteTime = Optional AbsoluteTime;
(* Represents an relative number of microseconds *)
Type RelativeTime = Long Integer;
Type OptionalRelativeTime = Optional RelativeTime;
(* ************************************************************************ *)
(* **************************** Version Related *************************** *)
Type Version = Record
major : Short Cardinal,
minor : Short Cardinal
End;
(* ************************************************************************ *)
(* ***************************** Intervals ******************************** *)
(* describes an inclusive range of unsigned numbers *)
Type UnsignedInclusiveInterval = Record
startValue : Cardinal,
endValue : Cardinal
End;
Type OptionalUnsignedInclusiveInterval = Optional UnsignedInclusiveInterval;
(* ************************************************************************ *)
(* ************************ Name Value Pairs ****************************** *)
(* simply a named attribute paired with some value *)
Type NameValuePair = Record
name : String,
value : Pickle
End;
Type NameValuePairSequence = Sequence Of NameValuePair;
Type NameSequence = Sequence Of NgBasic.String;
(* ************************************************************************ *)
(* ***************************** Exceptions ******************************* *)
Type OptionalPickle = Optional Pickle;
Type ExceptionInformation = Record
(* a human readable description of why the exception occurred *)
reasonPhrase : String,
(* if present, operation specific information on the details of why the
operation produced an exception *)
specificsData : OptionalPickle
End;
(* Certain operations, typically Gets or Puts, may return a WouldBlock or
Conflict exception when the operation would block for some reason or is
somehow in conflict with another operation (perhaps simultaneous Puts
on a Rendering) or operational semantics (perhaps a Put based on an
old version as determined through e-tag information for example).
The value optionally contained in the ExceptionInformation's Pickle is
operation specific. For a WouldBlock example, it could contain locking
information. Those knowledgeable about locking could attempt to extract
and make use of the lock information contained in the pickle. Those not
knowledgeable about locking could just disregard the value, but still have
knowledge that something is currently going on with the target object that
would cause them to block waiting for a result.
There may be situations where an implementation might quickly reify an
object in an object creation function and later determine that this object
really doesn't exist. There's a need to return an object doesn't exist
exception. Since this sort of 'system exception' information isn't
necessarily sent across the wire, it makes sense to create a user
exception, ObjectNotExist, for this sort of event. This is also useful if
this were to occur as the result of an async SendRenderingCall, where the
Report returned in the ReceiveRendering can contain an ObjectNotExist
exception.
*)
Exception WouldBlock : ExceptionInformation "Operation would have blocked" ;
Exception Conflict : ExceptionInformation
"Conflict with another operation or semantics" ;
Exception ObjectNotExist : ExceptionInformation
"Discriminator object doesn't exist" ;
(* ************************************************************************ *)
(* ***************************** NgObject ********************************* *)
(* NgObject forms a root class from which all Ng classes inherit *)
Type NgObjectSequence = Sequence Of NgObject;
Type NgObject = Object
Methods
(* Returns a stringified object reference of an object that supports the
Renderable interface. The denoted object can be asked for a Rendering
(e.g. text/isl, text/idl, text/midl, etc.) interface in which (the most
specific type) the object is defined. *)
GetInterfaceDefinitionSource () : String
End;
(* ************************************************************************ *)
(* ******************************** END *********************************** *)
(* ************************************************************************ *)
(* ************************************************************************ *)
(*
Version 1.3 ISL for HTTP-NG, Dan Larner, 3-19-98
This work is very preliminary - Comments welcomed and encouraged!
'xxx' marks areas where thought is definitly needed
Please send comments, suggestions, contributions, etc. to the http-ng
mailinglist, w3c-http-ng@w3.org and/or to larner@parc.xerox.com.
*)
(* ************************************************************************ *)
(* *********************** DataSource ************************************* *)
(* ************************************************************************ *)
Interface NgStream Brand "NG" Imports
NgBasic From ngbasic.isl
End;
(* This object type may be passed in invocations of operations meant for
asynchronous receipt of data (such as ReceiveRendering on a RenderingSink).
It allows the Sink side some control over the streaming operations.
NOTE: Methods invocations are assumed to be processed at the Source in the
order in which they were sent. *)
Type OptionalDataSource = Optional DataSource;
Type DataSource = Object
Supertypes NgBasic.NgObject End
Methods
(* Called to abort the streaming that is associated with this object *)
Asynchronous Abort (),
(* Called to pause the streaming that is associated with this object *)
Asynchronous Pause (),
(* Called to resume the streaming that is associated with this object *)
Asynchronous Resume (),
(* Called to have the streaming that is associated with this object resend
a range of data *)
Asynchronous Resend ( repeatRange : NgBasic.UnsignedInclusiveInterval ),
(* Called to suggest the streaming that is associated with this object
change its chunk size *)
Asynchronous SuggestChunkSize ( suggestedSize : Cardinal )
End;
(* This object type is used for control over a Sink.
NOTE: Methods invocations are assumed to be processed at the Sink in the
order in which they were sent. *)
Type DataSink = Object
Supertypes NgBasic.NgObject End
Methods
(* Called to tell the sink where control information can be sent *)
Asynchronous RegisterSourceControl (thesource : DataSource),
(* Called to indicate that no more data will be sent *)
Asynchronous Done ()
End;
(* ************************************************************************ *)
(* ******************************** END *********************************** *)
(* ************************************************************************ *)
(* ************************************************************************ *)
(*
Version 1.3 ISL for HTTP-NG, Dan Larner, 3-19-98
This work is very preliminary - Comments welcomed and encouraged!
'xxx' marks areas where thought is definitly needed
Please send comments, suggestions, contributions, etc. to the http-ng
mailinglist, w3c-http-ng@w3.org and/or to larner@parc.xerox.com.
*)
(* ************************************************************************ *)
(* *************************** Renderings ********************************* *)
(* ************************************************************************ *)
(* An Object of type Renderable is able to produce a rendering.
Examples renderings are a text description, a graphic, an html
page, an audio, etc.
An Object of type RenderingSink is able to asynchrounously receive
renderings.
*)
Interface NgRendering Brand "NG" Imports
NgBasic From ngbasic.isl,
IANA-Charsets-Registry From ianacharsets.isl,
NgCache From ngcache.isl,
NgStream From ngstream.isl
End;
(* ************************************************************************ *)
(* *************************** Rendering Types ***************************** *)
(* Note: any URIs here which are relative paths, are by default assumed to be
relative to the IANA registry - thus for example one might use "text/html".
xxx Need specification here about what the URI actually denotes *)
Type RenderingType = NgBasic.URI;
Type RenderingTypeSequence = NgBasic.URISequence;
Type RenderingEncoding = NgBasic.URI;
Type RenderingEncodingSequence = NgBasic.URISequence;
(* The requestor of a rendering may supply rendering preferences. The
preferences describe what characteristics a rendering must have.
For those members which are sequences, an empty sequence indicates no
particular preference, else the sequence is treated as an ordered
list of preferences. *)
(* ************************************************************************ *)
(* ******************** Rendering Preferences ***************************** *)
Type RenderingPreferences = Record
(* analogous to HTTP Accept, Accept-Charset, Accept-Encoding
Range, and User-Agent headers *)
(* Which content types are actually acceptable is obtained by, taking the
set of all types specified by allowContentTypes (some of which may
actually indicate a group of types via wildcard or other means), and
subtracting from it the set of all types specified by
disallowContentTypes. A zero length sequence for allowContentTypes
means all types. A zero length sequence for disallowContentTypes
means no types. Should the result allowContentTypes -
disallowContentTypes be empty, a NoRenderingMatch exception should be
raised from the receiving method. *)
allowContentTypes : RenderingTypeSequence,
disallowContentTypes : RenderingTypeSequence,
(* Which encodings are actually acceptable is obtained by, taking the set
of all types specified by allowEncodings (some of which may actually
indicate a group of encodings via wildcard or other means), and
subtracting from it the set of all types specified by disallowEncodings.
A zero length sequence for allowEncodings means all encodings. A zero
length sequence for disallowEncodings means no encodings. Should the
result allowEncodings - disallowEncodings be empty, a
NoRenderingMatch exception should be raised from the receiving
method. *)
allowEncodings : RenderingEncodingSequence,
disallowEncodings : RenderingEncodingSequence,
(* Acceptable Charsets of the rendering bytes before any encoding. A zero
length sequence means any charset is acceptable *)
acceptCharsets : IANA-Charsets-Registry.CharsetMIBEnumValueSequence,
(* Acceptible Locales of the rendering bytes before any encoding. A zero
length sequence means any locale is acceptable *)
acceptLocales : NgBasic.StringSequence,
(* If not supplied, indicates that the entire rendering is requested.
If supplied and of non-zero size, it indicates the range of bytes
desired from the rendering bytes before any encoding. If the interval
is supplied and is of zero size, effect is similar to Http's Head
method. *)
range : NgBasic.OptionalUnsignedInclusiveInterval,
(* xxx - Need specification here about what the URI actually denotes *)
userAgent : NgBasic.OptionalURI
End;
(* ************************************************************************ *)
(* *************************** Renderings ********************************* *)
(* actual bytes of a rendering *)
Type RenderingContentBytes = Sequence Of Byte;
Type RenderingChunk = Record
contentRange : NgBasic.OptionalUnsignedInclusiveInterval,
renderingBytes : RenderingContentBytes
End;
Type Rendering = Record
(* analogous to HTTP Content-Type, Content-Range, Content-Language,
Content-Encoding and Content-MD5 headers *)
(* Type of the rendering bytes before any encoding. *)
contentType : RenderingType,
(* Represents an ordered sequence of transformations that were applied to
the original contentType to arrive at the passed renderingBytes. e.g.
a,b,c means a( b( c(originalBytescontent))) A zero length sequence
means no transformations were applied to the original bytes.*)
contentEncoding : RenderingEncodingSequence,
(* If rangeEncoded is False, then contentRange is the range of the
rendering bytes before any encoding (unsupplied meaning all the bytes).
If rangeEncoded is True, then contentRange applies to the transformed
bytes, e.g. to a( b( c(originalBytescontent))). This is to allow for
the situation where there are intervening caches that have some of the
encoded bytes available, but have no ability (through design or policy)
to decode the bytes down to their original content. contentRange is
required with one exception: In the case where the RenderingPreferences
originally received specified a range of zero size (situation
treated similarly to HTTP Head), and the actual size is undeterminable
(e.g. a streaming live audio for example) then contentRange may be
unsupplied, and in this case, rangeEncoded should be ignored. *)
contentRange : NgBasic.OptionalUnsignedInclusiveInterval,
rangeEncoded : Boolean,
(* charset the rendering is in - If not supplied, default is US-ASCII *)
contentCharSet : IANA-Charsets-Registry.CharsetMIBEnumValue,
(* locale rendering is in e.g. en-us, de, etc. If unspecified default en *)
contentLocale : NgBasic.OptionalString,
(* encoded bytes of the rendering *)
renderingBytes : RenderingContentBytes
End;
Type OptionalRendering = Optional Rendering;
(* ************************************************************************ *)
(* ******************** Rendering Exceptions **************************** *)
(* Can't supply or accept any rendering meeting the preferences or input -
contains a RenderingPreferences (with the optional range and userAgent not
present) describing what is acceptable *)
Exception NoRenderingMatch : RenderingPreferences;
(* ************************************************************************ *)
(* ********************** RenderingSink Object **************************** *)
(* a RenderingProblemReport is used to pass information to asynchronous
callbacks that would have normally been passed back as an exception
from the synchronous version of the same sort of call *)
Type RenderingProblemReport = Union
noMatch : RenderingPreferences,
wouldBlock : NgBasic.ExceptionInformation,
objectNotExist : NgBasic.ExceptionInformation
End;
Type RenderingSink = Object
Supertypes NgStream.DataSink End
Methods
(* Called to tell the sink information about how to do caching. If this
is never called, then the Sink may cache in any manner it wishes, so
typically this will be called before any Renderings are sent.
Any call to this method remains in effect until a subsequent call
to this method occurs. *)
Asynchronous RegisterResponseCacheControl
( responseCacheInfo : NgCache.OptionalResponseCacheControl ),
(* RenderingProblem is called when an exception would have been raised from
calling GetRendering (with the same args as SendRendering) on the
Renderable object. This is basically to allow exceptions to be
passed back as the result of an async method. report is examined
for the same information as the exceptions that would have been raised
from calling GetRendering on the Renderable object. The calls to
the sink are considered Done if this method is called. *)
Asynchronous RenderingProblem ( report : RenderingProblemReport ),
(* ReceiveRendering is called as a result of a SendRendering call on a
Renderable. The calls to ReceiveRendering and ReceiveRenderingChunk
are considered complete when the Done method is called. *)
Asynchronous ReceiveRendering ( therendering : Rendering ),
(* ReceiveRenderingChunk is called to send rendering bytes that
differ only in contentRange and renderingBytes from the
Rendering in the last call to ReceiveRendering *)
Asynchronous ReceiveRenderingChunk ( thechunk : RenderingChunk ),
(* Called by the DataSource when something happens to its state such
that it needs to know what was last received by the Sink. If the
OptionalCardinal return value is supplied, it indicates (w.r.t
rangeEncoded) the next byte expected by the sink. If it is not
supplied, it indicates that the sink has not yet received any
rendering chunks.
*)
Resynchronize ( ) : NgBasic.OptionalCardinal
End;
(* ************************************************************************ *)
(* ************************* Renderable Object **************************** *)
Type Renderable = Object
Supertypes NgBasic.NgObject End
Methods
(* find out what types of renderings are available. The returned
RenderingPreferences describes what can be supplied. *)
GetAvailableRenderings () : RenderingPreferences
Raises NgBasic.WouldBlock, NgBasic.ObjectNotExist End,
(* GetRendering - The caller supplies a RenderingPreferences record
to specify the desired characteristics of the rendering.
The callee's method returns the appropriate range of bytes for the
best match it has for the rendering Preferences. If no match is
possible, the callee raises the NoRenderingMatch exception which
contains a RenderingPreferences describing what can be supplied.
*)
GetRendering ( renderingPreferences : RenderingPreferences,
requestCacheInfo : NgCache.OptionalRequestCacheControl,
out responseCacheInfo : NgCache.OptionalResponseCacheControl )
: Rendering
Raises NoRenderingMatch, NgBasic.WouldBlock, NgBasic.ObjectNotExist End,
(* SendRendering is just like GetRendering only instead of synchronously
returning the Rendering, it sends it asynchronously via calls to the
ReceiveRendering method on the supplied RenderingSink, The number of
bytes in each Rendering sent is up to the caller of ReceiveRendering,
but should be part of the range specified in renderingPreferences.
If present, suggestedChunkSize is a suggestion on how large to make
the data in the calls to ReceiveRendering. Typically, the implementation
of SendRendering would arrange the following sequence of calls on the
RenderingSink. (Where [] indicates optional and * indicates zero or more.)
When things are successful:
[RegisterSourceControl]
[RegisterResponseCacheControl]
ReceiveRendering
ReceiveRenderingChunk*
Done
When there's a problem:
RenderingProblem
See RenderingSink's ReceiveRendering method.*)
Asynchronous SendRendering(
renderingPreferences : RenderingPreferences,
requestCacheInfo : NgCache.OptionalRequestCacheControl,
renderSink : RenderingSink,
suggestedChunkSize : NgBasic.OptionalCardinal ),
(* A Synchronous version of SendRendering. The
intent is to allow the caller to simply know that the
call was received. *)
SendRenderingSynched(
renderingPreferences : RenderingPreferences,
requestCacheInfo : NgCache.OptionalRequestCacheControl,
renderSink : RenderingSink,
suggestedChunkSize : NgBasic.OptionalCardinal )
End;
(* ************************************************************************ *)
(* ***************** Renderable that you can 'Put' to ********************* *)
Type PutableRenderable = Object
Supertypes NgRendering.Renderable End
Methods
(* PutRendering - The caller supplies a Rendering record describing
the write operation to take place. If the supplied rendering input
is unacceptable (e.g. wrong type, etc.) the callee raises the
NoRenderingMatch exception which contains a RenderingPreferences
describing what is acceptable.
*)
PutRendering ( renderingInput : Rendering )
Raises NoRenderingMatch, NgBasic.WouldBlock, NgBasic.Conflict,
NgBasic.ObjectNotExist End
End;
(* ************************************************************************ *)
(* ******************************** END *********************************** *)
(* ************************************************************************ *)
(* ************************************************************************ *)
(* ************************************************************************ *)
(*
Version 1.3 ISL for HTTP-NG, Dan Larner, 3-19-98
This work is very preliminary - Comments welcomed and encouraged!
'xxx' marks areas where thought is definitly needed
Please send comments, suggestions, contributions, etc. to the http-ng
mailing list, w3c-http-ng@w3.org and/or to larner@parc.xerox.com.
*)
(* ************************************************************************ *)
(* *************************** Properties ********************************* *)
(* ************************************************************************ *)
(*
A PropertySet object contains a list of name value pairs.
In the Web for example, a WebDocument would inherit from PropertySet
so that various attributes (e.g. last modification time, authors, etc.)
could be accessed.
*)
Interface NgProperty Brand "NG" Imports
NgBasic From ngbasic.isl
End;
(* ************************************************************************ *)
(* ************************ Property Value Pairs ************************** *)
(* a property is simply a named attribute paired with some value *)
Type Property = NgBasic.NameValuePair;
Type PropertySequence = Sequence Of Property;
Type PropertyNames = NgBasic.NameSequence;
(* ************************************************************************ *)
(* ******************************** Exceptions **************************** *)
(* doesn't know these properties *)
Exception UnknownPropertyNames : PropertyNames ;
(* ************************************************************************ *)
(* *************************** Property Set Object ************************ *)
Type PropertySet = Object
Supertypes NgBasic.NgObject End
Methods
(* GetProperties returns a Set of the requested named 'Properties' and
their values. Sending an empty sequence of propertiesToGet is
equivalent to saying send all the properties. *)
GetProperties ( propertiesToGet : PropertyNames ) : PropertySequence
Raises UnknownPropertyNames, NgBasic.WouldBlock,
NgBasic.ObjectNotExist End
End;
(* ************************************************************************ *)
(* *********************** Putable Property Set Object ******************** *)
(* PropertyModification Records are used when modifying property sets *)
Type PropertyModificationKind = Enumeration Add, Remove, Change End;
Type PropertyModification = Record
propertyName : NgBasic.String,
modification : PropertyModificationKind,
(* present when modification is Add or Change *)
value : NgBasic.OptionalPickle
End;
Type PropertyModificationSequence = Sequence Of PropertyModification;
Type PutablePropertySet = Object
Supertypes PropertySet End
Methods
(* PutProperties sends a Set of the requested modifications.
Properties are added, removed and changed per the modification records.
If an exception is raised, no modifictions will have been made to the
PropertySet.
*)
PutProperties ( propertiesToSet : PropertyModificationSequence )
Raises UnknownPropertyNames, NgBasic.WouldBlock, NgBasic.Conflict,
NgBasic.ObjectNotExist End
End;
(* ************************************************************************ *)
(* ******************************** END *********************************** *)
(* ************************************************************************ *)
(* ************************************************************************ *)
(*
Version 1.3 ISL for HTTP-NG, Dan Larner, 3-19-98
This work is very preliminary - Comments welcomed and encouraged!
'xxx' marks areas where thought is definitly needed
Please send comments, suggestions, contributions, etc. to the http-ng
mailing list, w3c-http-ng@w3.org and/or to larner@parc.xerox.com.
*)
(* ************************************************************************ *)
(* *************************** Web Documents ****************************** *)
(* ************************************************************************ *)
(* Defines the concept of Web Documents *)
(* Import iluhttp so that we can offer easy compatability with the existing
web - that is, anything object inheriting from iluhttp.Resource will
support Get, Head, Put and Post methods as we know them in the current web
*)
Interface NgDocument Brand "NG" Imports
iluhttp From iluhttp.isl,
NgRendering From ngrendering.isl,
NgRendering From ngrendering.isl,
NgCache From ngcache.isl,
NgProperty From ngproperty.isl,
NgStream From ngstream.isl
End;
(* ************************************************************************ *)
(* ******************** RenderingAndPropertiesSink *********************** *)
(* a RenderingProblemReport is used to pass information to asynchronous
callbacks that would have normally been passed back as an exception
from the synchronous version of the same sort of call *)
Type PropertiesProblemReport = Union
wouldBlock : NgBasic.ExceptionInformation,
unknownProperties : NgProperty.PropertyNames
End;
Type RenderingAndPropertiesSink = Object
Supertypes NgRendering.RenderingSink End
Methods
(* PropertyProblem is called when a property related exception would
have been raised from calling GetRenderingAndProperties (with the
same args as SendRenderingAndProperties) This is basically to
allow exceptions to be passed back as the result of an async method.
report is examined for the same information as the exceptions that
would have been raised from calling GetProperties on the WebDocument
object. The calls to the sink are considered Done if this method is
called. *)
Asynchronous PropertiesProblem( report : PropertiesProblemReport),
(* ReceiveProperties is called as a result of a
SendRenderingAndProperties call on a WebDocument. *)
Asynchronous ReceiveProperties (theproperties : NgProperty.PropertySequence)
End;
(* ************************************************************************ *)
(* ************************** WebDocument Interface *********************** *)
(* A WebDocument is meant to be an NG version of roughly what Web documents
are today *)
Type WebDocument = Object
Supertypes
NgRendering.Renderable,
NgProperty.PropertySet
End
(* ************
Properties which may be accessible via the property set interface
include
Authors - a NgBasic.StringSequence, The authors of this document
CreationTime - a NgBasic.AbsoluteTime
Version - a NgBasic.Version,
Summary a NgBasic.String - some (human readable) summary of what
the document is
Note: The next two are analogous to the lastModified and expires members
of the ResponseCacheControl Record
LastModificationTime a NgBasic.AbsoluteTime
ExpectedChange an NgBasic.AbsoluteTime - when this document is expected
to change
*********** *)
Methods
(* basically a combination of the GetRendering and GetProperties methods *)
GetRenderingAndProperties (
renderingPreferences : NgRendering.RenderingPreferences,
requestCacheInfo : NgCache.OptionalRequestCacheControl,
out responseCacheInfo : NgCache.OptionalResponseCacheControl,
propertiesToGet : NgProperty.PropertyNames,
Out theproperties : NgProperty.PropertySequence
) : NgRendering.Rendering
Raises NgRendering.NoRenderingMatch,
NgProperty.UnknownPropertyNames,
NgBasic.WouldBlock,
NgBasic.ObjectNotExist End,
(* SendRenderingAndProperties is just like GetRenderingAndProperties only
instead of synchronusly returning the results, they are sent
asynchronously via calls to the ReceiveRenderingAndProperties method
on the supplied RenderingAndPropertiesSink. The number of bytes in each
Rendering sent is up to the caller of ReceiveRenderingAndProperties, but
should be part of the range specified in renderingPreferences.
If present, suggestedChunkSize is a suggestion on how large to make
the data in the calls to ReceiveRenderingAndProperties. Typically, the
implementation of SendRenderingAndProperties would arrange the following
sequence of calls on the RenderingAndPropertiesSink. (Where [] indicates
optional and * indicates zero or more.)
When things are successful:
[RegisterSourceControl]
[RegisterResponseCacheControl]
ReceiveProperties
ReceiveRendering
ReceiveRenderingChunk*
Done
When there's a problem:
RenderingProblem OR PropertiesProblem
See
RenderingAndPropertiesSink's ReceiveRenderingAndProperties method.*)
Asynchronous SendRenderingAndProperties (
renderingPreferences : NgRendering.RenderingPreferences,
requestCacheInfo : NgCache.OptionalRequestCacheControl,
propertiesToGet : NgProperty.PropertyNames,
renderPropSink : RenderingAndPropertiesSink,
suggestedChunkSize : NgBasic.OptionalCardinal ),
(* A Synchronous version of SendRenderingAndProperties. The
intent is to allow the caller to simply know that the
call was received. *)
SendRenderingAndPropertiesSynched(
renderingPreferences : NgRendering.RenderingPreferences,
requestCacheInfo : NgCache.OptionalRequestCacheControl,
propertiesToGet : NgProperty.PropertyNames,
renderPropSink : RenderingAndPropertiesSink,
suggestedChunkSize : NgBasic.OptionalCardinal )
End;
(* ************************************************************************ *)
(* *************** WebDocument that you can 'Put' to ********************** *)
Type PutableWebDocument = Object
Supertypes
NgDocument.WebDocument,
NgRendering.PutableRenderable,
NgProperty.PutablePropertySet
End
Methods
(* basically combination of the PutRendering and PutProperties methods *)
PutRenderingAndProperties (
renderingInput : NgRendering.Rendering,
propertiesToSet : NgProperty.PropertyModificationSequence)
Raises NgRendering.NoRenderingMatch,
NgProperty.UnknownPropertyNames,
NgBasic.WouldBlock,
NgBasic.Conflict, NgBasic.ObjectNotExist End
End;
(* ************************************************************************ *)
(* ************** HTTPCompatibleWebDocument Interface ************ ******** *)
(* A HTTPCompatibleWebDocument is a WebDocument that can also be accessed via
HTTP 1.x Get, Head and Post calls. *)
Type HTTPCompatibleWebDocument = Object
Supertypes
WebDocument,
iluhttp.Resource
End
;
(* ************************************************************************ *)
(* ******************************** END *********************************** *)
(* ************************************************************************ *)
(* ************************************************************************ *)
(*
Version 1.3 ISL for HTTP-NG, Dan Larner, 3-19-98
This work is very preliminary - Comments welcomed and encouraged!
'xxx' marks areas where thought is definitly needed
Please send comments, suggestions, contributions, etc. to the http-ng
mailing list, w3c-http-ng@w3.org and/or to larner@parc.xerox.com.
*)
(* ************************************************************************ *)
(* *************************** FormProcessors ***************************** *)
(* ************************************************************************ *)
(* An Object of type FormProcessor is able to process Form based input, and
produce an appropriate rendering as a response.
*)
Interface NgFormProcessor Brand "NG" Imports
NgBasic From ngbasic.isl,
IANA-Charsets-Registry From ianacharsets.isl,
NgCache From ngcache.isl,
NgRendering From ngrendering.isl
End;
(* ************************************************************************ *)
(* ********************* Form entries ************************************ *)
(* a Form input element is simply a named form field paired with some value *)
Type FormInputElement = NgBasic.NameValuePair;
Type FormInputElementSequence = Sequence Of FormInputElement;
Type FormInputElementNames = NgBasic.NameSequence;
(* ************************************************************************ *)
(* ******************** FormProcessing Exceptions ************************* *)
(* The listed form inputs has invalid values *)
Exception InvalidFormEntries : FormInputElementNames;
(* ************************************************************************ *)
(* ********************** ProcessedFormSink ****************************** *)
(* a FormProblemReport is used to pass information to asynchronous
callbacks that would have normally been passed back as an exception
from the synchronous version of the same sort of call *)
Type FormProblemReport = Union
invalidEntries : FormInputElementNames,
conflict : NgBasic.ExceptionInformation,
objectNotExist : NgBasic.ExceptionInformation
End;
Type OptionalFormProblemReport = Optional FormProblemReport;
(* A ProcessedFormSink is basically a NgRendering.RenderingSink
except that there are some more problems that can be reported *)
Type ProcessedFormSink = Object
Supertypes NgRendering.RenderingSink End
Methods
(* FormProblem is called when a Form related exception would have been
raised from calling ProcessForm (with the same args as SendForm) on the
FormProcessor object. This is basically to allow exceptions to be
passed back as the result of an async method. report is examined
for the same information as the exceptions that would have been raised
from calling ProcessForm on the FormProcessor object. The calls to
the sink are considered Done if this method is called. *)
Asynchronous FormProblem ( report : FormProblemReport )
End;
(* ************************************************************************ *)
(* *********************** FormProcessor Object *************************** *)
Type FormProcessor = Object
Supertypes NgBasic.NgObject End
Methods
(* ProcessForm - The caller supplies a FormInputElementSequence describing
the form data. If the supplied formEntries input is unacceptable (e.g.
wrong type, etc.) the callee raises the InvalidFormEntries exception
which contains a sequence of the names of the entries which were
unacceptable, else a Rendering is returned.
*)
ProcessForm ( formEntries : FormInputElementSequence,
out responseCacheInfo : NgCache.OptionalResponseCacheControl )
: NgRendering.Rendering
Raises InvalidFormEntries, NgBasic.WouldBlock, NgBasic.Conflict,
NgBasic.ObjectNotExist End,
(* SendFormReply is just like ProcessForm only instead of synchronously
returning the Rendering, it sends it asynchronously via a call to the
ReceiveFormResult method on the supplied ProcessedFormSink *)
Asynchronous SendFormReply ( formEntries : FormInputElementSequence,
formSink : ProcessedFormSink ),
(* A Synchronous version of SendForm. The intent is to allow the
caller to simply know that the call was received. *)
SendFormReplySynched(
formEntries : FormInputElementSequence,
formSink : ProcessedFormSink )
End;
(* ************************************************************************ *)
(* ******************************** END *********************************** *)
(* ************************************************************************ *)
(* ************************************************************************ *)
(*
Version 1.3 ISL for HTTP-NG, Dan Larner, 3-19-98
This work is very preliminary - Comments welcomed and encouraged!
'xxx' marks areas where thought is definitly needed
Please send comments, suggestions, contributions, etc. to the http-ng
mailing list, w3c-http-ng@w3.org and/or to larner@parc.xerox.com.
*)
(* ************************************************************************ *)
(* ************************************************************************ *)
(* *************************** Caching Control **************************** *)
(* ************************************************************************ *)
(* Caching control provides cache and proxy relevant information that
may be sent along with requests and responses. This mostly mimics
the cache related headers and Cache-Control header values found in
HTTP 1.1. See that specification for the semantics.
*)
Interface NgCache Brand "NG" Imports
NgBasic From ngbasic.isl
End;
(* ************************************************************************ *)
(* *************************** Entity tags ******************************** *)
Type EntityTag = NgBasic.String;
Type OptionalEntityTag = Optional NgBasic.String;
Type EntityTagSequence = Sequence Of EntityTag;
Type EntityTagOrDate = Union
etag : EntityTag,
ifdate : NgBasic.AbsoluteTime
End;
(* ************************************************************************ *)
(* ***************** Request Cache Control ******************************** *)
Type RequestCacheControl = Record
(* analogous to HTTP Cache-Control header values *)
noCache : Boolean,
noStore : Boolean,
noTransform : Boolean,
onlyIfCached : Boolean,
(* analogous to HTTP If-ModifiedSince, If-Match, If-None-Match and
If-Range headers *)
ifModifiedSince : NgBasic.OptionalAbsoluteTime,
ifMatch : EntityTagSequence,
ifNoneMatch : EntityTagSequence,
ifRange : EntityTagOrDate
End;
Type OptionalRequestCacheControl = Optional RequestCacheControl;
(* ************************************************************************ *)
(* ***************** Response Cache Control ******************************* *)
Type ResponseCacheControl = Record
(* analogous to HTTP Cache-Control header values*)
okPublic : Boolean,
isPrivate : Boolean,
noCache : Boolean,
noStore : Boolean,
noTransform : Boolean,
mustRevalidate : Boolean,
proxyRevalidate : Boolean,
maxAge : NgBasic.OptionalRelativeTime,
sMaxAge : NgBasic.OptionalRelativeTime,
(* analogous to HTTP Age, Vary, Etag, Last-Modified and Expires headers *)
age : NgBasic.OptionalRelativeTime,
vary : NgBasic.StringSequence,
entityTag : OptionalEntityTag,
lastModified : NgBasic.OptionalAbsoluteTime,
expires : NgBasic.OptionalAbsoluteTime
End;
Type OptionalResponseCacheControl = Optional ResponseCacheControl;
(* ************************************************************************ *)
(* ******************************** END *********************************** *)
(* ************************************************************************ *)
(* ************************************************************************ *)
(*
Version 1.3 ISL for HTTP-NG, Dan Larner, 3-19-98
This work is very preliminary - Comments welcomed and encouraged!
'xxx' marks areas where thought is definitly needed
Please send comments, suggestions, contributions, etc. to the http-ng
mailing list, w3c-http-ng@w3.org and/or to larner@parc.xerox.com.
*)
(* ************************************************************************ *)
(* *************************** IANA Charsets ****************************** *)
(* ************************************************************************ *)
(* Defines standard charsets. *)
Interface IANA-Charsets-Registry Brand "NG" ;
Type CharsetMIBEnumValue = Short Cardinal;
Type CharsetMIBEnumValueSequence = Sequence Of CharsetMIBEnumValue;
Type OptionalCharsetMIBEnumValue = Optional CharsetMIBEnumValue;
Constant US-ASCII : CharsetMIBEnumValue = 3;
(* XXX need to complete the list *)
(* ************************************************************************ *)
(* ******************************** END *********************************** *)
(* ************************************************************************ *)