]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blobdiff - src/allmydata/scripts/common_http.py
Flesh out "tahoe magic-folder status" command
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / scripts / common_http.py
index f2c060bd826f6506e04d40d1ed3a09b653511d4b..1964672bd2b416973592fb26ca85c317b62cae3c 100644 (file)
@@ -1,7 +1,12 @@
 
+import os
 from cStringIO import StringIO
 import urlparse, httplib
-import allmydata # for __version__
+import allmydata # for __full_version__
+
+from allmydata.util.encodingutil import quote_output
+from allmydata.scripts.common import TahoeError
+from socket import error as socket_error
 
 # copied from twisted/web/client.py
 def parse_url(url, defaultPort=None):
@@ -22,13 +27,24 @@ def parse_url(url, defaultPort=None):
         path = "/"
     return scheme, host, port, path
 
+class BadResponse(object):
+    def __init__(self, url, err):
+        self.status = -1
+        self.reason = "Error trying to connect to %s: %s" % (url, err)
+        self.error = err
+    def read(self):
+        return ""
+
 
 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")
+        raise TypeError("do_http body must be a bytestring, not unicode")
     else:
+        # We must give a Content-Length header to twisted.web, otherwise it
+        # seems to get a zero-length file. I suspect that "chunked-encoding"
+        # may fix this.
         assert body.tell
         assert body.seek
         assert body.read
@@ -41,15 +57,20 @@ def do_http(method, url, body=""):
         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("User-Agent", allmydata.__full_version__ + " (tahoe-client)")
+    c.putheader("Accept", "text/plain, application/octet-stream")
     c.putheader("Connection", "close")
 
     old = body.tell()
-    body.seek(0, 2)
+    body.seek(0, os.SEEK_END)
     length = body.tell()
     body.seek(old)
     c.putheader("Content-Length", str(length))
-    c.endheaders()
+
+    try:
+        c.endheaders()
+    except socket_error, err:
+        return BadResponse(url, err)
 
     while True:
         data = body.read(8192)
@@ -59,7 +80,20 @@ def do_http(method, url, body=""):
 
     return c.getresponse()
 
+
+def format_http_success(resp):
+    return "%s %s" % (resp.status, quote_output(resp.reason, quotemarks=False))
+
+def format_http_error(msg, resp):
+    return "%s: %s %s\n%s" % (msg, resp.status, quote_output(resp.reason, quotemarks=False),
+                              quote_output(resp.read(), quotemarks=False))
+
 def check_http_error(resp, stderr):
     if resp.status < 200 or resp.status >= 300:
-        print >>stderr, "error %d during HTTP request" % resp.status
+        print >>stderr, format_http_error("Error during HTTP request", resp)
         return 1
+
+
+class HTTPError(TahoeError):
+    def __init__(self, msg, resp):
+        TahoeError.__init__(self, format_http_error(msg, resp))