generic-uri ::= scheme: [ user-host-address-and-path ] [ parameter ] [ search ] [ fragment ]
relative-uri ::= [ user-host-address-and-path ] [ parameter ] [ search ] [ fragment ]
file-uri ::= file: [ //host ] [ path ] [ parameter ]
data-uri ::= data: [ type ] [ subtype ] [ parameter ] [ data ]
ftp-uri ::= ftp: [ user-password-host-address-and-path ] [ parameter ]
gopher-uri ::= gopher: [ host-address ] [ /gtype selector [ gsearch [ gstring ] ] ] [ parameter ]
http-uri ::= http: [ host-address-and-path ] [ parameter ] [ search ] [ fragment ]
mailto-uri ::= mailto: [ user@ ] host [ :port ] [ parameter ] [ ?headers ]
nntp-uri ::= nntp: [ user-password-host-address ] [ /group [ /article ] ] [ parameter ]
pop-uri ::= pop: [ user authorisation@ ] [ host ] [ :port ] [ message ] [ parameter ]
channel-uri ::= channel: channel-identifier
none-uri ::= none: string
oav-uri ::= oav: variable :path [ parameter ]
Information about URIs is stored in an OAV mapping referred to as the urispace. This includes the parsing pattern, the generation format, the list of parts, and definitions of methods. OAV permits objects to be delegated, and for parents to be searched. All this flexibility is available for resolving information about URIs. The uri command consults this OAV mapping to parse URIs and evaluate methods on them.
The uri command has a static mapping compiled into it to provide a default set of definitions. A default internal urispace is initially defined. This space can be supplemented by defining another mapping, possibly delegating to or copying from the original default mapping. The new mapping can then be made the new urispace.
The wyrm-urispace defines standard URLs for file, data, ftp, gopher, http, mailto, news, nntp, pop, relative, and nonstandard URLs for oav mappings and no resource. A generic URI is defined which should match most other URIs. The methods open, get, put, delete, status, and children methods are defined for each of these URIs, though in many cases the default implementation is to return an error that the operation is not really implemented.
If a uri has the scheme, the parse pattern is gotten with the OAV key uri.scheme.+pattern, the parts list with uri.scheme.+parts, the generate format with uri.scheme.+generate, and the Tcl code implementing method with uri.scheme.method. And these keys may end up delegated elsewhere.
New URIs can be added to a modifiable urispace with the oav command. For example a "qwerty" scheme can be defined with
oav put [uri space] uri.qwerty.+parts {scheme text}
oav put [uri space] uri.qwerty.+pattern ^(qwerty):(.*)$}
oav put [uri space] uri.qwerty.+generate {s:s}
oav method [uri space] uri.qwerty.open {uri args} {open "qwerty" r}
A generic URI is provided by defining the keys uri.+pattern, uri.+parts, uri.+generate, and uri.method for generic methods. If a scheme is not (completely) defined in the urispace, then the OAV delegation rules will find these generic pattern, parts, generate, and methods for what is not specifically defined.
And keys not conforming to these patterns may be in the urispace. They are not directly accessed, but they may be delegated to or used for routines other than uri.
URIs are parsed with a regular expressions. Parentheses surround the subexpression matching parts. "(?:...)" is used to group subexpressions that are not parts. For example
The parts list is a list name of parts corresponding to the parenthesised (but not "(?:...)" parenthesised) subexpressions.
The parsing is similar to
After the URI has been parsed into parts, possibly editted, it is regenerated with its scheme's generate format. The format is a string of formatters and literal characters; formatters are single letters each of which corresponds to one part, and the brackets '(' and ')'. The URI parts are generated in parts list order under the control of formatter letters.
The open, get, and put methods transfer a resource as a string of bytes. Each URI should provide a method to open a channel to the resource so that caller can use puts and read to move the resource bytes, or the URI should provide a get and put methods to move the bytes en masse. The generic URI provides an open method that can open a data channel using specific get and put methods, and it provides get and put methods that can use a specific open method. A URI can also provide all three open, get, and put methods.
A URI for read only resource need only define the get method; the put method will eventually fail.
The generic methods use an additional method arguments to detect when the URI does not provide an open and a get or put method.
Open a channel to the URI resource. Caller is responsible for closing the channel; a writeable channel might not actually transfer the resource bytes until the channel is closed.
Get the bytes of a URI resource. The entire resource is transferred in the one call; no further action is necessary to release or close the resource.
Put the bytes to a URI resource. The entire resource is transferred in the one call; no further action is necessary to release or close the resource.
Deletes the URI resource. The generic implementation fails with the error message it cannot delete the resource.
Return information about the resource. This is a key/value pairs list which alway contains the keys "exists" and "uri". Any key/value pairs on the command define default pairs in the result.These default are replaced by real status values provided by the resource.
The status method always succeeds to return some kind of list. If the resource does not exists, it returns the key "exists" with the value 0; other failures can be indicated by additional keys.