blob: 11cf3769b463d37707f4a75ecac754df2be86bc8 [file] [log] [blame]
#!/usr/bin/python
# Copyright 2011 Google Inc. All Rights Reserved.
#
"""A command-line tool for uploading to gfiber-dropbox.appspot.com."""
__author__ = 'apenwarr@google.com (Avery Pennarun)'
import httplib
import os.path
import signal
import sys
import time
import urllib
import zlib
import options
optspec = """
upload-logs [options...] <filenames...>
--
s,server= The server URL [https://gfiber-dropbox.appspot.com]
k,key= Add a key/value pair (format "-k key=value")
stdin= Also upload stdin, with the given virtual filename
"""
class HttpError(Exception):
def __init__(self, result):
self.status = result.status
self.reason = result.reason
Exception.__init__(self, str(self))
def __str__(self):
return 'http status %d: %s' % (self.status, self.reason)
def UrlSplit(url):
proto, rest = urllib.splittype(url)
hostport, rest = urllib.splithost(rest)
path, query = urllib.splitquery(rest)
return proto, hostport, path, query
def HttpDo(method, url, content, headers):
"""Make an HTTP request and return the result."""
proto, hostport, path, query = UrlSplit(url)
assert proto.lower() in ('http', 'https')
connection = httplib.HTTPConnection(hostport)
if query:
path += '?' + query
connection.request(method, path, content, headers)
result = connection.getresponse()
if result.status != 200:
raise HttpError(result)
return result.read()
def UploadFile(url, filename, fileobj, keys):
"""Actually upload the given file to the server."""
while filename.startswith('/'):
filename = filename[1:]
start_url = os.path.join(url, 'upload', filename)
if keys:
start_url += '?' + urllib.urlencode(keys)
upload_url = HttpDo('GET', start_url, None, headers={})
splitter = 'foo-splitter-%f' % time.time()
content_type = 'multipart/form-data; boundary=%s' % splitter
basecontent = zlib.compress(fileobj.read())
attachment = ('--%(splitter)s\r\n'
'Content-Disposition: form-data; name="file";'
' filename="%(filename)s"\r\n'
'\r\n'
'%(data)s'
'\r\n'
'--%(splitter)s--\r\n'
'\r\n'
% dict(splitter=splitter,
filename=filename,
data=basecontent))
try:
HttpDo('POST', upload_url, attachment,
headers={'Content-Type': content_type,
'Content-Length': len(attachment)})
except HttpError, e:
if e.status == 302:
pass
else:
raise
else:
raise Exception('expected http response code 302')
def main():
# set an alarm, in case our HTTP client (or anything else) hangs
# for any reason
signal.alarm(60)
o = options.Options(optspec)
(opt, flags, extra) = o.parse(sys.argv[1:]) #pylint: disable-msg=W0612
if not extra and not opt.stdin:
o.fatal('at least one filename and/or --stdin expected')
keys = []
for k, v in flags:
if k in ('-k', '--key'):
keys.append(tuple(v.split('=', 1)))
if opt.stdin:
UploadFile(opt.server, opt.stdin, sys.stdin, keys)
for filename in extra:
UploadFile(opt.server, filename, open(filename), keys)
if __name__ == '__main__':
main()