POST /uri?t=mkdir
PUT /uri?t=mkdir
- Create a new directory (either empty or with some initial children) and
- return its write-cap as the HTTP response body. This does not make the newly
- created directory visible from the virtual drive. The "PUT" operation is
- provided for backwards compatibility: new code should use POST.
+ Create a new empty directory and return its write-cap as the HTTP response
+ body. This does not make the newly created directory visible from the
+ virtual drive. The "PUT" operation is provided for backwards compatibility:
+ new code should use POST.
- Initial children are provided in the "children" field of the POST form, or
- as the request body of the PUT request. This is more efficient than doing
- separate mkdir and add-children operations. If this value is empty, the new
- directory will be empty.
+POST /uri?t=mkdir-with-children
+
+ Create a new directory, populated with a set of child nodes, and return its
+ write-cap as the HTTP response body. The new directory is not attached to
+ any other directory: the returned write-cap is the only reference to it.
+
+ Initial children are provided in the "children" field of the POST form. This
+ is more efficient than doing separate mkdir and add-children operations. If
+ this value is empty, the new directory will be empty.
If not empty, it will be interpreted as a JSON-encoded dictionary of
children with which the new directory should be populated, using the same
intermediate directories as necessary. If the named target directory already
exists, this will make no changes to it.
- If a directory is created, it will be populated with initial children via
- the PUT request body or POST 'children' form field, as described above.
+ If the final directory is created, it will be empty.
This will return an error if a blocking file is present at any of the parent
names, preventing the server from creating the necessary parent directory.
The write-cap of the new directory will be returned as the HTTP response
body.
+POST /uri/$DIRCAP/[SUBDIRS../]SUBDIR?t=mkdir-with-children
+
+ Like above, but if the final directory is created, it will be populated with
+ initial children via the POST 'children' form field, as described above in
+ the /uri?t=mkdir-with-children operation.
+
POST /uri/$DIRCAP/[SUBDIRS../]?t=mkdir&name=NAME
Create a new empty directory and attach it to the given existing directory.
- This will create additional intermediate directories as necessary. The new
- directory will be populated with initial children via the PUT request body
- or POST 'children' form field, as described above.
+ This will create additional intermediate directories as necessary.
The URL of this form points to the parent of the bottom-most new directory,
whereas the previous form has a URL that points directly to the bottom-most
new directory.
+POST /uri/$DIRCAP/[SUBDIRS../]?t=mkdir-with-children&name=NAME
+
+ As above, but the new directory will be populated with initial children via
+ the POST 'children' form field, as described in /uri?t=mkdir-with-children
+ above.
+
=== Get Information About A File Or Directory (as JSON) ===
GET /uri/$FILECAP?t=json
POST /uri?t=mkdir
- This creates a new directory, but does not attach it to the virtual
+ This creates a new empty directory, but does not attach it to the virtual
filesystem.
If a "redirect_to_result=true" argument is provided, then the HTTP response
"false"), then the HTTP response body will simply be the write-cap of the
new directory.
- It accepts the same initial-children arguments as described in earlier
- t=mkdir sections, but these are unlikely to be useful from a browser form.
-
POST /uri/$DIRCAP/[SUBDIRS../]?t=mkdir&name=CHILDNAME
- This creates a new directory as a child of the designated SUBDIR. This will
- create additional intermediate directories as necessary.
+ This creates a new empty directory as a child of the designated SUBDIR. This
+ will create additional intermediate directories as necessary.
If a "when_done=URL" argument is provided, the HTTP response will cause the
web browser to redirect to the given URL. This provides a convenient way to
when_done= argument, the HTTP response will simply contain the write-cap of
the directory that was just created.
- It accepts the same initial-children arguments as described in earlier
- t=mkdir sections, but these are unlikely to be useful from a browser form.
-
=== Uploading a File ===
d.addCallback(self.failUnlessNodeKeysAre, [])
return d
- def test_PUT_NEWDIRURL_initial_children(self):
- (newkids, filecap1, filecap2, filecap3,
- dircap) = self._create_initial_children()
- d = self.PUT(self.public_url + "/foo/newdir?t=mkdir",
- simplejson.dumps(newkids))
- def _check(uri):
- n = self.s.create_node_from_uri(uri.strip())
- d2 = self.failUnlessNodeKeysAre(n, newkids.keys())
- d2.addCallback(lambda ign:
- self.failUnlessChildURIIs(n, u"child-imm", filecap1))
- d2.addCallback(lambda ign:
- n.get_child_and_metadata_at_path(u"child-imm"))
- d2.addCallback(lambda (c1, md1):
- self.failUnlessEqual(md1["metakey1"], "metavalue1"))
- d2.addCallback(lambda ign:
- self.failUnlessChildURIIs(n, u"child-mutable",
- filecap2))
- d2.addCallback(lambda ign:
- self.failUnlessChildURIIs(n, u"child-mutable-ro",
- filecap3))
- d2.addCallback(lambda ign:
- self.failUnlessChildURIIs(n, u"dirchild", dircap))
- return d2
- d.addCallback(_check)
- d.addCallback(lambda res:
- self.failUnlessNodeHasChild(self._foo_node, u"newdir"))
- d.addCallback(lambda res: self._foo_node.get(u"newdir"))
- d.addCallback(self.failUnlessNodeKeysAre, newkids.keys())
- d.addCallback(lambda res: self._foo_node.get(u"newdir"))
- d.addCallback(self.failUnlessChildURIIs, u"child-imm", filecap1)
- return d
-
def test_POST_NEWDIRURL_initial_children(self):
(newkids, filecap1, filecap2, filecap3,
dircap) = self._create_initial_children()
- d = self.POST(self.public_url + "/foo/newdir?t=mkdir",
+ d = self.POST(self.public_url + "/foo/newdir?t=mkdir-with-children",
children=simplejson.dumps(newkids))
def _check(uri):
n = self.s.create_node_from_uri(uri.strip())
def test_POST_mkdir_initial_children(self):
newkids, filecap1, ign, ign, ign = self._create_initial_children()
- d = self.POST(self.public_url + "/foo", t="mkdir", name="newdir",
- children=simplejson.dumps(newkids))
+ d = self.POST(self.public_url + "/foo", t="mkdir-with-children",
+ name="newdir", children=simplejson.dumps(newkids))
d.addCallback(lambda res:
self.failUnlessNodeHasChild(self._foo_node, u"newdir"))
d.addCallback(lambda res: self._foo_node.get(u"newdir"))
def test_POST_mkdir_no_parentdir_initial_children(self):
(newkids, filecap1, filecap2, filecap3,
dircap) = self._create_initial_children()
- d = self.POST("/uri?t=mkdir", children=simplejson.dumps(newkids))
+ d = self.POST("/uri?t=mkdir-with-children",
+ children=simplejson.dumps(newkids))
def _after_mkdir(res):
self.failUnless(res.startswith("URI:DIR"), res)
n = self.s.create_node_from_uri(res)
d.addCallback(_after_mkdir)
return d
+ def test_POST_mkdir_no_parentdir_unexpected_children(self):
+ # the regular /uri?t=mkdir operation is specified to ignore its body.
+ # Only t=mkdir-with-children pays attention to it.
+ (newkids, filecap1, filecap2, filecap3,
+ dircap) = self._create_initial_children()
+ d = self.shouldHTTPError("POST t=mkdir unexpected children",
+ 400, "Bad Request",
+ "t=mkdir does not accept children=, "
+ "try t=mkdir-with-children instead",
+ self.POST, "/uri?t=mkdir", # without children
+ children=simplejson.dumps(newkids))
+ return d
+
def test_POST_noparent_bad(self):
d = self.shouldHTTPError("POST /uri?t=bogus", 400, "Bad Request",
"/uri accepts only PUT, PUT?t=mkdir, "
d.addCallback(self.failUnlessIsEmptyJSON)
return d
- def test_PUT_mkdir_initial_children(self):
- (newkids, filecap1, filecap2, filecap3,
- dircap) = self._create_initial_children()
- d = self.PUT("/uri?t=mkdir", simplejson.dumps(newkids))
- def _check(uri):
- n = self.s.create_node_from_uri(uri.strip())
- d2 = self.failUnlessNodeKeysAre(n, newkids.keys())
- d2.addCallback(lambda ign:
- self.failUnlessChildURIIs(n, u"child-imm", filecap1))
- d2.addCallback(lambda ign:
- self.failUnlessChildURIIs(n, u"child-mutable",
- filecap2))
- d2.addCallback(lambda ign:
- self.failUnlessChildURIIs(n, u"child-mutable-ro",
- filecap3))
- d2.addCallback(lambda ign:
- self.failUnlessChildURIIs(n, u"dirchild", dircap))
- return d2
- d.addCallback(_check)
- return d
-
def test_POST_check(self):
d = self.POST(self.public_url + "/foo", t="check", name="bar.txt")
def _done(res):
return results[0]
return default
-def convert_initial_children_json(nodemaker, initial_children_json):
+def convert_children_json(nodemaker, children_json):
"""I convert the JSON output of GET?t=json into the dict-of-nodes input
to both dirnode.create_subdirectory() and
client.create_directory(initial_children=)."""
initial_children = {}
- if initial_children_json:
- data = simplejson.loads(initial_children_json)
+ if children_json:
+ data = simplejson.loads(children_json)
for (name, (ctype, propdict)) in data.iteritems():
name = unicode(name)
writecap = propdict.get("rw_uri")
IOpHandleTable, NeedOperationHandleError, \
boolean_of_arg, get_arg, get_root, parse_replace_arg, \
should_create_intermediate_directories, \
- getxmlfile, RenderMixin, humanize_failure, convert_initial_children_json
+ getxmlfile, RenderMixin, humanize_failure, convert_children_json
from allmydata.web.filenode import ReplaceMeMixin, \
FileNodeHandler, PlaceHolderNodeHandler
from allmydata.web.check_results import CheckResults, \
else:
if DEBUG: print " terminal"
# terminal node
- if (method,t) in [ ("POST","mkdir"), ("PUT","mkdir") ]:
+ if (method,t) in [ ("POST","mkdir"), ("PUT","mkdir"),
+ ("POST", "mkdir-with-children") ]:
if DEBUG: print " making final directory"
# final directory
- if method == "POST":
+ kids = {}
+ if (method,t) == ("POST", "mkdir-with-children"):
kids_json = get_arg(req, "children", "")
- else:
- req.content.seek(0)
- kids_json = req.content.read()
- kids = convert_initial_children_json(self.client.nodemaker,
- kids_json)
+ kids = convert_children_json(self.client.nodemaker,
+ kids_json)
d = self.node.create_subdirectory(name, kids)
d.addCallback(make_handler_for,
self.client, self.node, name)
if t == "mkdir":
d = self._POST_mkdir(req)
+ elif t == "mkdir-with-children":
+ d = self._POST_mkdir_with_children(req)
elif t == "mkdir-p":
# TODO: docs, tests
d = self._POST_mkdir_p(req)
return d
def _POST_mkdir(self, req):
+ name = get_arg(req, "name", "")
+ if not name:
+ # our job is done, it was handled by the code in got_child
+ # which created the final directory (i.e. us)
+ return defer.succeed(self.node.get_uri()) # TODO: urlencode
+ name = name.decode("utf-8")
+ replace = boolean_of_arg(get_arg(req, "replace", "true"))
+ kids = {}
+ d = self.node.create_subdirectory(name, kids, overwrite=replace)
+ d.addCallback(lambda child: child.get_uri()) # TODO: urlencode
+ return d
+
+ def _POST_mkdir_with_children(self, req):
name = get_arg(req, "name", "")
if not name:
# our job is done, it was handled by the code in got_child
name = name.decode("utf-8")
replace = boolean_of_arg(get_arg(req, "replace", "true"))
kids_json = get_arg(req, "children", "")
- kids = convert_initial_children_json(self.client.nodemaker, kids_json)
+ kids = convert_children_json(self.client.nodemaker, kids_json)
d = self.node.create_subdirectory(name, kids, overwrite=replace)
d.addCallback(lambda child: child.get_uri()) # TODO: urlencode
return d
return unlinked.POSTUnlinkedCHK(req, self.client)
if t == "mkdir":
return unlinked.POSTUnlinkedCreateDirectory(req, self.client)
+ elif t == "mkdir-with-children":
+ return unlinked.POSTUnlinkedCreateDirectoryWithChildren(req,
+ self.client)
errmsg = ("/uri accepts only PUT, PUT?t=mkdir, POST?t=upload, "
"and POST?t=mkdir")
raise WebError(errmsg, http.BAD_REQUEST)
from nevow import rend, url, tags as T
from allmydata.immutable.upload import FileHandle
from allmydata.web.common import getxmlfile, get_arg, boolean_of_arg, \
- convert_initial_children_json
+ convert_children_json, WebError
from allmydata.web import status
def PUTUnlinkedCHK(req, client):
def PUTUnlinkedCreateDirectory(req, client):
# "PUT /uri?t=mkdir", to create an unlinked directory.
- req.content.seek(0)
- kids_json = req.content.read()
- kids = convert_initial_children_json(client.nodemaker, kids_json)
- d = client.create_dirnode(initial_children=kids)
+ d = client.create_dirnode()
d.addCallback(lambda dirnode: dirnode.get_uri())
# XXX add redirect_to_result
return d
return d
def POSTUnlinkedCreateDirectory(req, client):
+ # "POST /uri?t=mkdir", to create an unlinked directory.
+ kids_json = get_arg(req, "children", None)
+ if kids_json is not None:
+ raise WebError("t=mkdir does not accept children=, "
+ "try t=mkdir-with-children instead",
+ http.BAD_REQUEST)
+ d = client.create_dirnode()
+ redirect = get_arg(req, "redirect_to_result", "false")
+ if boolean_of_arg(redirect):
+ def _then_redir(res):
+ new_url = "uri/" + urllib.quote(res.get_uri())
+ req.setResponseCode(http.SEE_OTHER) # 303
+ req.setHeader('location', new_url)
+ req.finish()
+ return ''
+ d.addCallback(_then_redir)
+ else:
+ d.addCallback(lambda dirnode: dirnode.get_uri())
+ return d
+
+def POSTUnlinkedCreateDirectoryWithChildren(req, client):
# "POST /uri?t=mkdir", to create an unlinked directory.
kids_json = get_arg(req, "children", "")
- kids = convert_initial_children_json(client.nodemaker, kids_json)
+ kids = convert_children_json(client.nodemaker, kids_json)
d = client.create_dirnode(initial_children=kids)
redirect = get_arg(req, "redirect_to_result", "false")
if boolean_of_arg(redirect):