From: Zooko O'Whielacronx Date: Fri, 7 Dec 2007 00:17:02 +0000 (-0700) Subject: add POST /uri?t=upload and tests thereof X-Git-Url: https://git.rkrishnan.org/components/%22news.html/reliability?a=commitdiff_plain;h=8ad2e85fdf855d46509c1efcc9d21dd0ae46be5c;p=tahoe-lafs%2Ftahoe-lafs.git 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. --- diff --git a/src/allmydata/test/test_web.py b/src/allmydata/test/test_web.py index 300018a2..c3188b48 100644 --- a/src/allmydata/test/test_web.py +++ b/src/allmydata/test/test_web.py @@ -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", diff --git a/src/allmydata/webish.py b/src/allmydata/webish.py index 6353dbeb..84aa6ba4 100644 --- a/src/allmydata/webish.py +++ b/src/allmydata/webish.py @@ -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