tahoe-lafs/docs/webapi.txt

351 lines
14 KiB
Plaintext

Writing "8011" into CLIENTDIR/webport causes the client to run a webserver on
port 8011. Writing "tcp:8011:interface=127.0.0.1" into CLIENTDIR/webport does
the same but binds to the loopback interface, ensuring that only the programs
on the local host can connect. Using
"ssl:8011:privateKey=mykey.pem:certKey=cert.pem" would run an SSL server. See
twisted.application.strports for more details.
If CLIENTDIR/webpassword exists, it will be used (somehow) to require HTTP
Digest Authentication for all webserver connections.
The client provides some small number of "virtual drives". In the 0.4.0
release, this number is two: the first is the global shared vdrive, the
second is the private non-shared vdrive. We will call these "global" and
"private" for now.
For the purpose of this document, let us assume that the vdrives currently
contain the following directories and files:
global/
global/Documents/
global/Documents/notes.txt
private/
private/Pictures/
private/Pictures/tractors.jpg
== vdrive ==
Within the webserver, there is a tree of resources. The top-level "vdrive"
resource gives access to files and directories in all of the user's virtual
drives. For example, the URL that corresponds to notes.txt would be:
FILEURL = http://localhost:8011/vdrive/global/Documents/notes.txt
and the URL for tractors.jpg would be:
http://localhost:8011/vdrive/private/Pictures/tractors.jpg
In addition, each directory has a corresponding URL. The Pictures URL is:
DIRURL = http://localhost:8011/vdrive/private/Pictures
Now, what can we do with these URLs? By varying the HTTP "method"
(GET/PUT/POST/DELETE) and by appending a type-indicating query argument, we
control how what we want to do with the data and how it should be presented.
In the following examples, FILEURL and DIRURL are abbreviations for the
previously listed examples. In addition. NEWFILEURL and NEWDIRURL are URLs
for files and directories which do not yet exist.
=== Files ===
GET FILEURL
This simply retrives the contents of the file at the given place in the
vdrive. The Content-Type is set according to the vdrive's metadata (if
available) or by using the usual filename-extension-magic built into most
webservers. The file's contents are provided in the body of the HTTP
response.
(thought: we could conceivably provide some measure of gathering-peers
progress and pre-plaintext status information by emitting some extra
X-Tahoe-Status headers. Of course, once the headers are done and we start
sending plaintext, we have to stop sending such headers)
PUT NEWFILEURL
This uploads a file to the given place in the vdrive. It will create
intermediate directory nodes as necessary. The file's contents are taken
from the body of the HTTP request. For convenience, the HTTP response
contains the URI that results from uploading the file, although the client
is not obligated to do anything with the URI. According to the HTTP/1.1
specification (rfc2068), this should return a 200 (OK) code when modifying
and existing file, and a 201 (Created) code when creating a new file.
To use this, run 'curl -T localfile http://localhost:8011/vdrive/global/newfile'
DELETE FILEURL
This deletes the given file from the vdrive. Note that this *does not*
delete any parent directories, so a sequence of 'PUT NEWFILEURL' and
'DELETE NEWFILEURL' does not necessarily return the vdrive to its original
state (it may leave some intermediate directory nodes).
GET FILEURL?t=json
This returns machine-parseable information about the file in the HTTP
response body, including file size, metadata (like Content-Type), and URIs.
This information is also required to contain a flag that distinguishes
between files and directories. Programatic clients are expected to use this
query before actually downloading the file's contents.
The JSON data is as follows:
[ 'filenode', { 'mutable': bool, 'uri': file_uri, 'size': bytes } ]
GET FILEURL?t=download&localfile=$FILENAME
This instructs the client to download the given file and write its contents
into the local filesystem at $FILENAME. This request will only be accepted
from an HTTP client connection originating at 127.0.0.1 . This request is
most useful when the client node and the HTTP client are operated by the
same user. $FILENAME should be an absolute pathname.
(thoughts: we could use either the response headers or the response body
to indicate download progress)
PUT NEWFILEURL?t=upload&localfile=$FILENAME
This uploads file to the vdrive and gets the contents from a file in the
client's local filesystem. As with GET, this request will only be accepted
from an HTTP connection originating from 127.0.0.1.
(we could indicate upload progress too. The response body could contain
the URI of the uploaded file)
GET FILEURL?t=uri
This returns the URI of the given file in the HTTP response body.
GET FILEURL?t=readonly-uri
This also returns the URI of the given file. For now, all files are
immutable, so t=uri and t=readonly-uri return the same value. In the
future, when we have mutable files, they will return different values.
=== Directories ===
GET DIRURL
This returns an HTML page, intended to be used by humans, which contains
HREF links to all files and directories reachable from this dirnode. These
HREF links do not have a t= argument, meaning that a human who follows them
will get pages also meant for a human. It also contains forms to upload new
files, and to delete files and directories. These forms use POST methods to
do their job.
GET DIRURL?t=json
This returns machine-parseable information about this directory in the HTTP
response body. This information first contains a flag to indicate that
DIRURL referenced a directory (as opposed to a file). Then it contains a
flag to indicate whether this is a read-write dirnode or a read-only
dirnode. Finally it also contains information about the children of this
directory, probably as a mapping from child name to a set of metadata about
the child (basically the same data that would appear in a corresponding
GET?t=json of the child itself). A programmatic client should be able to use
the information from this query to display filesystem navigation choices to
a human user.
The JSON data is as follows:
[ 'dirnode', { 'mutable': bool, 'uri': uri, 'children': children } ]
where 'children' is a dictionary in which the keys are child names
and the values depend upon whether the child is a file or a directory:
'foo.txt': [ 'filenode', { 'mutable': bool, 'uri': uri, 'size': bytes } ]
'subdir': [ 'dirnode', { 'mutable': bool, 'uri': uri } ]
note that the value is the same as the JSON representation of the
corresponding FILEURL or DIRURL (except that dirnodes do not recurse).
GET DIRURL?t=uri
GET DIRURL?t=readonly-uri
Return a URI for this dirnode in the HTTP response body. If the dirnode is
read-only, the t=uri and t=readonly-uri responses will be the same.
GET DIRURL?t=manifest
Return an HTML-formatted manifest of the given directory, for debugging.
PUT NEWDIRURL?t=mkdir
Create a new empty directory at the given path. The HTTP response contains
the URI of the given directory, although the client is not obligated to do
anything with it.
DELETE DIRURL
This deletes the given directory (and all of its children). Note that this
*does not* delete any parent directories, so a sequence of 'PUT
NEWDIRURL?t=mkdir' and 'DELETE NEWDIRURL does not necessarily return the
vdrive to its original state (it may leave some intermediate directory
nodes).
GET DIRURL?t=download&localdir=$DIRNAME
This instructs the client to perform a recursive download of the given
directory and all its descendant files and directories, writing the results
to the local filesystem starting at DIRNAME.
(thoughts: we could use the response headers or the response body to
indicate download progress)
PUT NEWDIRURL?t=upload&localdir=$DIRNAME
This instructs the client to perform a recursive upload of a directory on
the local filesystem into the vdrive at the given location. NEWDIRURL will
be created if necessary. When the operation is complete, the directory
referenced by NEWDIRURL will contain all of the files and directories that
were present in DIRNAME, so this is equivalent to the unix commands:
mkdir -p NEWDIRURL; cp -r DIRNAME/* NEWDIRURL/
Note that the "curl" utility can be used to provoke this sort of recursive
upload, since the -T option will make it use an HTTP 'PUT':
curl -T /dev/null 'http://localhost:8011/vdrive/global/newdir?t=upload&localdir=/home/user/directory-to-upload'
GET DIRURL?t=rename-form&name=$CHILDNAME
This provides a useful facility to browser-based user interfaces.
It returns a page containing a form targetting the POST DIRURL t=rename
functionality listed below, with the provided $CHILDNAME present in the
'from_name' field of that form. i.e. this presents a form offering to
rename $CHILDNAME, requesting the new name, and submitting POST rename
== POST Forms ==
POST DIRURL
t=upload
name=childname (optional)
file=newfile
This instructs the client to upload a file into the given dirnode. We need
this because forms are the only way for a web browser to upload a file
(browsers do not know how to do PUT or DELETE). The file's contents and the
new child name will be included in the form's arguments. This can only be
used to upload a single file at a time. To avoid confusion, name= is not
allowed to contain a slash (a 400 Bad Request error will result).
POST DIRURL
t=mkdir
name=childname
This instructs the client to create a new empty directory. The name of the
new child directory will be included in the form's arguments.
POST DIRURL
t=uri
name=childname
uri=newuri
This instructs the client to attach a child that is referenced by URI (just
like the PUT NEWFILEURL?t=uri method). The name and URI of the new child
will be included in the form's arguments.
POST DIRURL
t=delete
name=childname
This instructs the client to delete a file from the given dirnode. The name
of the child to be deleted will be included in the form's arguments.
POST DIRURL
t=rename
from_name=oldchildname
to_name=newchildname
This instructs the client to rename a child within the given dirnode. The
child specified by 'from_name' is removed, and reattached as a child named
for 'to_name'. This is unconditional and will replace any child already
present under 'to_name', akin to 'mv -f' in unix parlance.
== URI ==
http://localhost:8011/uri/$URI
A separate top-level resource namespace ("uri" instead of "vdrive") is used
to get access to files and dirnodes that are indexed directly by URI,
rather than by going through the vdrive. The resource thus referenced is
used the same way as if it were accessed through the vdrive, including
child-resource-traversal behavior. For example, if the URI corresponds to a
file, then
GET http://localhost:8011/uri/$URI
would retrieve the contents of the file. Since files accessed this way do
not have a naturally-occurring filename (from which a MIME-type can be
derived), one can be specified using a 'filename=' query argument. This
filename is also the one used if the 'save=true' argument is set, which
adds a 'Content-Disposition: attachment' header to prompt most web browsers
to save the file to disk rather than attempting to display it:
GET http://localhost:8011/uri/$URI?filename=foo.jpg
GET http://localhost:8011/uri/$URI?filename=foo.jpg&save=true
If the URI corresponds to a directory, then:
PUT http://localhost:8011/uri/$URI/subdir/newfile?localfile=$FILENAME
would upload a file (with contents taken from the local filesystem) to a
new file in a subdirectory of the referenced dirnode.
Note that since tahoe URIs may contain slashes (in particular, dirnode URIs
contain a FURL, which resembles a regular HTTP URL and starts with pb://),
when URIs are used in this form, they must be specially quoted. All slashes
in the URI must be replaced by '!' characters.
PUT NEWFILEURL?t=uri
This attaches a child (either a file or a directory) to the vdrive at the
given location. The URI is provided in the body of the HTTP request. This
can be used to attach a shared directory to the vdrive. Intermediate
directories are created on-demand just like with the regular PUT command.
GET http://localhost:8011/uri?uri=$URI
This causes a redirect to /uri/$URI, and retains any additional query
arguments (like filename= or save=). This is for the convenience of web
forms which allow the user to paste in a URI (obtained through some
out-of-band channel, like IM or email).
Note that this form only redirects to the specific node indicated by the
URI: unlike the GET /uri/$URI form, you cannot traverse to child nodes by
appending additional path segments to the URL.
The $URI provided as a query argument is allowed to contain slashes. The
redirection provided will escape the slashes with exclamation points, as
described above.
== XMLRPC ==
http://localhost:8011/xmlrpc
This resource provides an XMLRPC server on which all of the previous
operations can be expressed as function calls taking a "pathname" argument.
This is provided for applications that want to think of everything in terms
of XMLRPC.
listdir(vdrivename, path) -> dict of (childname -> (stuff))
put(vdrivename, path, contents) -> URI
get(vdrivename, path) -> contents
mkdir(vdrivename, path) -> URI
put_localfile(vdrivename, path, localfilename) -> URI
get_localfile(vdrivename, path, localfilename)
put_localdir(vdrivename, path, localdirname) # recursive
get_localdir(vdrivename, path, localdirname) # recursive
put_uri(vdrivename, path, URI)
etc..