add POST /uri?t=upload and tests thereof

Hm...  I refactored processing of segments in a way that I marked as "XXX HELP
I AM YUCKY", and then I ran out of time for rerefactoring it before I
committed.  At least all the tests pass.
This commit is contained in:
Zooko O'Whielacronx 2007-12-06 17:17:02 -07:00
parent 841c1a8509
commit 8ad2e85fdf
2 changed files with 86 additions and 28 deletions

View File

@ -14,7 +14,7 @@ from allmydata.interfaces import IURI, INewDirectoryURI, IReadonlyNewDirectoryUR
# create a fake uploader/downloader, and a couple of fake dirnodes, then
# create a webserver that works against them
class MyClient(service.MultiService):
class FakeClient(service.MultiService):
nodeid = "fake_nodeid"
basedir = "fake_basedir"
def get_versions(self):
@ -62,7 +62,7 @@ class MyClient(service.MultiService):
class WebMixin(object):
def setUp(self):
self.s = MyClient()
self.s = FakeClient()
self.s.startService()
self.ws = s = webish.WebishServer("0")
s.allow_local_access(True)
@ -799,6 +799,9 @@ class Web(WebMixin, unittest.TestCase):
d.addCallback(_check)
return d
def failUnlessCHKURIHasContents(self, got_uri, contents):
self.failUnless(FakeCHKFileNode.all_contents[got_uri] == contents)
def test_PUT_NEWDIRURL_localdir(self):
localdir = os.path.abspath("web/PUT_NEWDIRURL_localdir")
# create some files there
@ -888,6 +891,22 @@ class Web(WebMixin, unittest.TestCase):
self.NEWFILE_CONTENTS))
return d
def test_POST_upload_no_link(self):
d = self.POST("/uri/", t="upload",
file=("new.txt", self.NEWFILE_CONTENTS))
d.addCallback(self.failUnlessCHKURIHasContents, self.NEWFILE_CONTENTS)
return d
def test_POST_upload_no_link_whendone(self):
d = self.POST("/uri/", t="upload", when_done="/",
file=("new.txt", self.NEWFILE_CONTENTS))
d.addBoth(self.shouldRedirect, "/")
# XXX Test that resulting welcome page has a "most recent
# upload", the URI of which points to the file contents that
# you just uploaded.
return d
test_POST_upload_no_link_whendone.todo = "Not yet implemented."
def test_POST_upload_mutable(self):
# this creates a mutable file
d = self.POST(self.public_url + "/foo", t="upload", mutable="true",

View File

@ -1210,6 +1210,33 @@ class URIPUTHandler(rend.Page):
req.setHeader("content-type", "text/plain")
return "/uri only accepts PUT and PUT?t=mkdir"
class URIPOSTHandler(rend.Page):
def renderHTTP(self, ctx):
req = inevow.IRequest(ctx)
assert req.method == "POST"
t = ""
if "t" in req.args:
t = req.args["t"][0]
if t in ("", "upload"):
# "POST /uri", to create an unlinked file.
fileobj = req.fields["file"].file
uploadable = upload.FileHandle(fileobj)
d = IClient(ctx).upload(uploadable)
# that fires with the URI of the new file
return d
if t == "mkdir":
# "PUT /uri?t=mkdir", to create an unlinked directory.
d = IClient(ctx).create_empty_dirnode()
d.addCallback(lambda dirnode: dirnode.get_uri())
return d
req.setResponseCode(http.BAD_REQUEST)
req.setHeader("content-type", "text/plain")
return "/uri accepts only PUT, PUT?t=mkdir, POST?t=upload" # XXX check this -- what about POST?t=mkdir?
class Root(rend.Page):
@ -1220,32 +1247,44 @@ class Root(rend.Page):
client = IClient(ctx)
req = inevow.IRequest(ctx)
if segments[0] == "uri":
if len(segments) == 1 or segments[1] == '':
if "uri" in req.args:
uri = req.args["uri"][0].replace("/", "!")
there = url.URL.fromContext(ctx)
there = there.clear("uri")
there = there.child("uri").child(uri)
return there, ()
if len(segments) == 1 and req.method == "PUT":
# /uri
# either "PUT /uri" to create an unlinked file, or
# "PUT /uri?t=mkdir" to create an unlinked directory
return URIPUTHandler(), ()
if len(segments) < 2:
return rend.NotFound
uri = segments[1].replace("!", "/")
d = defer.maybeDeferred(client.create_node_from_uri, uri)
d.addCallback(lambda node: VDrive(node, "from-uri"))
d.addCallback(lambda vd: vd.locateChild(ctx, segments[2:]))
def _trap_KeyError(f):
f.trap(KeyError)
return rend.FourOhFour(), ()
d.addErrback(_trap_KeyError)
return d
elif segments[0] == "xmlrpc":
raise NotImplementedError()
segments = list(segments) # XXX HELP I AM YUCKY!
while segments and not segments[-1]:
segments.pop()
if not segments:
segments.append('')
segments = tuple(segments)
if segments:
if segments[0] == "uri":
if len(segments) == 1 or segments[1] == '':
if "uri" in req.args:
uri = req.args["uri"][0].replace("/", "!")
there = url.URL.fromContext(ctx)
there = there.clear("uri")
there = there.child("uri").child(uri)
return there, ()
if len(segments) == 1:
# /uri
if req.method == "PUT":
# either "PUT /uri" to create an unlinked file, or
# "PUT /uri?t=mkdir" to create an unlinked directory
return URIPUTHandler(), ()
elif req.method == "POST":
# "POST /uri?t=upload&file=newfile" to upload an unlinked
# file
return URIPOSTHandler(), ()
if len(segments) < 2:
return rend.NotFound
uri = segments[1].replace("!", "/")
d = defer.maybeDeferred(client.create_node_from_uri, uri)
d.addCallback(lambda node: VDrive(node, "from-uri"))
d.addCallback(lambda vd: vd.locateChild(ctx, segments[2:]))
def _trap_KeyError(f):
f.trap(KeyError)
return rend.FourOhFour(), ()
d.addErrback(_trap_KeyError)
return d
elif segments[0] == "xmlrpc":
raise NotImplementedError()
return rend.Page.locateChild(self, ctx, segments)
child_webform_css = webform.defaultCSS