cli: simplify code by using stdlib's httplib module

This commit is contained in:
Brian Warner 2007-10-11 22:29:23 -07:00
parent 4361b32f2d
commit f0e727867a
5 changed files with 88 additions and 137 deletions

View File

@ -62,3 +62,4 @@ class NoDefaultBasedirMixin(BasedirMixin):
if not self.basedirs:
raise usage.UsageError("--basedir must be provided")

View File

@ -0,0 +1,60 @@
from cStringIO import StringIO
import urlparse, httplib
import allmydata # for __version__
# copied from twisted/web/client.py
def parse_url(url, defaultPort=None):
url = url.strip()
parsed = urlparse.urlparse(url)
scheme = parsed[0]
path = urlparse.urlunparse(('','')+parsed[2:])
if defaultPort is None:
if scheme == 'https':
defaultPort = 443
else:
defaultPort = 80
host, port = parsed[1], defaultPort
if ':' in host:
host, port = host.split(':')
port = int(port)
if path == "":
path = "/"
return scheme, host, port, path
def do_http(method, url, body=""):
if isinstance(body, str):
body = StringIO(body)
elif isinstance(body, unicode):
raise RuntimeError("do_http body must be a bytestring, not unicode")
else:
assert body.tell
assert body.seek
assert body.read
scheme, host, port, path = parse_url(url)
if scheme == "http":
c = httplib.HTTPConnection(host, port)
elif scheme == "https":
c = httplib.HTTPSConnection(host, port)
else:
raise ValueError("unknown scheme '%s', need http or https" % scheme)
c.putrequest(method, path)
c.putheader("Hostname", host)
c.putheader("User-Agent", "tahoe_cli/%s" % allmydata.__version__)
c.putheader("Connection", "close")
old = body.tell()
body.seek(0, 2)
length = body.tell()
body.seek(old)
c.putheader("Content-Length", str(length))
c.endheaders()
while True:
data = body.read(8192)
if not data:
break
c.send(data)
return c.getresponse()

View File

@ -1,44 +1,9 @@
#! /usr/bin/python
import re
import urllib, httplib
import urlparse
import urllib
import simplejson
# copied from twisted/web/client.py
def _parse(url, defaultPort=None):
url = url.strip()
parsed = urlparse.urlparse(url)
scheme = parsed[0]
path = urlparse.urlunparse(('','')+parsed[2:])
if defaultPort is None:
if scheme == 'https':
defaultPort = 443
else:
defaultPort = 80
host, port = parsed[1], defaultPort
if ':' in host:
host, port = host.split(':')
port = int(port)
if path == "":
path = "/"
return scheme, host, port, path
def do_http(method, url, body=""):
scheme, host, port, path = _parse(url)
if scheme == "http":
c = httplib.HTTPConnection(host, port)
elif scheme == "https":
c = httplib.HTTPSConnection(host, port)
else:
raise ValueError("unknown scheme '%s', need http or https" % scheme)
c.putrequest(method, path)
import allmydata
c.putheader("User-Agent", "tahoe_mv/%s" % allmydata.__version__)
c.putheader("Content-Length", str(len(body)))
c.endheaders()
c.send(body)
return c.getresponse()
from allmydata.scripts.common_http import do_http
def mv(nodeurl, root_uri, frompath, topath, stdout, stderr):
if nodeurl[-1] != "/":
@ -48,6 +13,9 @@ def mv(nodeurl, root_uri, frompath, topath, stdout, stderr):
nodetype, attrs = simplejson.loads(data)
uri = attrs.get("rw_uri") or attrs["ro_uri"]
# simplejson always returns unicode, but we know that it's really just a
# bytestring.
uri = str(uri)
put_url = url + topath + "?t=uri"
resp = do_http("PUT", put_url, uri)

View File

@ -1,8 +1,7 @@
#!/usr/bin/env python
import re, socket, urllib
NODEURL_RE=re.compile("http://([^:]*)(:([1-9][0-9]*))?")
import urllib
from allmydata.scripts.common_http import do_http
def put(nodeurl, root_uri, local_fname, vdrive_fname, verbosity,
stdout, stderr):
@ -11,66 +10,21 @@ def put(nodeurl, root_uri, local_fname, vdrive_fname, verbosity,
@return: a Deferred which eventually fires with the exit code
"""
mo = NODEURL_RE.match(nodeurl)
host = mo.group(1)
port = int(mo.group(3))
url = "/uri/%s/" % urllib.quote(root_uri.replace("/","!"))
if nodeurl[-1] != "/":
nodeurl += "/"
url = nodeurl + "uri/%s/" % urllib.quote(root_uri.replace("/","!"))
if vdrive_fname:
url += vdrive_fname
infileobj = open(local_fname, "rb")
infileobj.seek(0, 2)
infilelen = infileobj.tell()
infileobj.seek(0, 0)
resp = do_http("PUT", url, infileobj)
so = socket.socket()
so.connect((host, port,))
if resp.status in (200, 201,):
print >>stdout, "%s %s" % (resp.status, resp.reason)
return 0
CHUNKSIZE=2**16
data = "PUT %s HTTP/1.1\r\nConnection: close\r\nContent-Length: %s\r\nHostname: %s\r\n\r\n" % (url, infilelen, host,)
while data:
try:
sent = so.send(data)
except Exception, le:
print >>stderr, "got socket error: %s" % (le,)
return -1
if sent == len(data):
data = infileobj.read(CHUNKSIZE)
else:
data = data[sent:]
respbuf = []
data = so.recv(CHUNKSIZE)
while data:
respbuf.append(data)
data = so.recv(CHUNKSIZE)
so.shutdown(socket.SHUT_WR)
data = so.recv(CHUNKSIZE)
while data:
respbuf.append(data)
data = so.recv(CHUNKSIZE)
respstr = ''.join(respbuf)
headerend = respstr.find('\r\n\r\n')
if headerend == -1:
headerend = len(respstr)
header = respstr[:headerend]
RESP_RE=re.compile("^HTTP/[0-9]\.[0-9] ([0-9]*) *([A-Za-z_ ]*)") # This regex is soooo ad hoc... --Zooko 2007-08-16
mo = RESP_RE.match(header)
if mo:
code = int(mo.group(1))
word = mo.group(2)
if code in (200, 201,):
print >>stdout, "%s %s" % (code, word,)
return 0
print >>stderr, respstr[headerend:]
print >>stderr, "error, got %s %s" % (resp.status, resp.reason)
print >>stderr, resp.read()
return 1
def main():

View File

@ -1,8 +1,7 @@
#!/usr/bin/env python
import re, socket, urllib
NODEURL_RE=re.compile("http://([^:]*)(:([1-9][0-9]*))?")
import urllib
from allmydata.scripts.common_http import do_http
def rm(nodeurl, root_uri, vdrive_pathname, verbosity, stdout, stderr):
"""
@ -10,51 +9,20 @@ def rm(nodeurl, root_uri, vdrive_pathname, verbosity, stdout, stderr):
@return: a Deferred which eventually fires with the exit code
"""
mo = NODEURL_RE.match(nodeurl)
host = mo.group(1)
port = int(mo.group(3))
url = "/uri/%s/" % urllib.quote(root_uri.replace("/","!"))
if nodeurl[-1] != "/":
nodeurl += "/"
url = nodeurl + "uri/%s/" % urllib.quote(root_uri.replace("/","!"))
if vdrive_pathname:
url += vdrive_pathname
so = socket.socket()
so.connect((host, port,))
resp = do_http("DELETE", url)
CHUNKSIZE=2**16
data = "DELETE %s HTTP/1.1\r\nConnection: close\r\nHostname: %s\r\n\r\n" % (url, host,)
sent = so.send(data)
if resp.status in (200,):
print >>stdout, "%s %s" % (resp.status, resp.reason)
return 0
respbuf = []
data = so.recv(CHUNKSIZE)
while data:
respbuf.append(data)
data = so.recv(CHUNKSIZE)
so.shutdown(socket.SHUT_WR)
data = so.recv(CHUNKSIZE)
while data:
respbuf.append(data)
data = so.recv(CHUNKSIZE)
respstr = ''.join(respbuf)
headerend = respstr.find('\r\n\r\n')
if headerend == -1:
headerend = len(respstr)
header = respstr[:headerend]
RESP_RE=re.compile("^HTTP/[0-9]\.[0-9] ([0-9]*) *([A-Za-z_ ]*)") # This regex is soooo ad hoc... --Zooko 2007-08-16
mo = RESP_RE.match(header)
if mo:
code = int(mo.group(1))
word = mo.group(2)
if code == 200:
print >>stdout, "%s %s" % (code, word,)
return 0
print >>stderr, respstr[headerend:]
print >>stderr, "error, got %s %s" % (resp.status, resp.reason)
print >>stderr, resp.read()
return 1
def main():