]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - src/allmydata/scripts/common_http.py
Unicode fixes.
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / scripts / common_http.py
1
2 from cStringIO import StringIO
3 import urlparse, httplib
4 import allmydata # for __full_version__
5
6 from allmydata.util.stringutils import quote_output
7 from allmydata.scripts.common import TahoeError
8
9
10 # copied from twisted/web/client.py
11 def parse_url(url, defaultPort=None):
12     url = url.strip()
13     parsed = urlparse.urlparse(url)
14     scheme = parsed[0]
15     path = urlparse.urlunparse(('','')+parsed[2:])
16     if defaultPort is None:
17         if scheme == 'https':
18             defaultPort = 443
19         else:
20             defaultPort = 80
21     host, port = parsed[1], defaultPort
22     if ':' in host:
23         host, port = host.split(':')
24         port = int(port)
25     if path == "":
26         path = "/"
27     return scheme, host, port, path
28
29
30 def do_http(method, url, body=""):
31     if isinstance(body, str):
32         body = StringIO(body)
33     elif isinstance(body, unicode):
34         raise TypeError("do_http body must be a bytestring, not unicode")
35     else:
36         # We must give a Content-Length header to twisted.web, otherwise it
37         # seems to get a zero-length file. I suspect that "chunked-encoding"
38         # may fix this.
39         assert body.tell
40         assert body.seek
41         assert body.read
42     scheme, host, port, path = parse_url(url)
43     if scheme == "http":
44         c = httplib.HTTPConnection(host, port)
45     elif scheme == "https":
46         c = httplib.HTTPSConnection(host, port)
47     else:
48         raise ValueError("unknown scheme '%s', need http or https" % scheme)
49     c.putrequest(method, path)
50     c.putheader("Hostname", host)
51     c.putheader("User-Agent", allmydata.__full_version__ + " (tahoe-client)")
52     c.putheader("Accept", "text/plain, application/octet-stream")
53     c.putheader("Connection", "close")
54
55     old = body.tell()
56     body.seek(0, 2)
57     length = body.tell()
58     body.seek(old)
59     c.putheader("Content-Length", str(length))
60     c.endheaders()
61
62     while True:
63         data = body.read(8192)
64         if not data:
65             break
66         c.send(data)
67
68     return c.getresponse()
69
70
71 def format_http_success(resp):
72     return "%s %s" % (resp.status, quote_output(resp.reason, quotemarks=False))
73
74 def format_http_error(msg, resp):
75     return "%s: %s %s\n%s" % (msg, resp.status, quote_output(resp.reason, quotemarks=False),
76                               quote_output(resp.read(), quotemarks=False))
77
78 def check_http_error(resp, stderr):
79     if resp.status < 200 or resp.status >= 300:
80         print >>stderr, format_http_error("Error during HTTP request", resp)
81         return 1
82
83
84 class HTTPError(TahoeError):
85     def __init__(self, msg, resp):
86         TahoeError.__init__(format_http_error(msg, resp))