run all sync requests through one function

This commit is contained in:
Damien Elmes 2011-12-07 17:56:39 +09:00
parent 9b76a4669c
commit 4b190c3586

View file

@ -395,8 +395,9 @@ class LocalServer(Syncer):
class HttpSyncer(object): class HttpSyncer(object):
def _vars(self): def __init__(self, hkey=None, con=None):
return dict(k=self.hkey) self.hkey = hkey
self.con = con or httpCon()
def assertOk(self, resp): def assertOk(self, resp):
if resp['status'] != '200': if resp['status'] != '200':
@ -408,19 +409,23 @@ class HttpSyncer(object):
# costly. We could send it as a raw post, but more HTTP clients seem to # costly. We could send it as a raw post, but more HTTP clients seem to
# support file uploading, so this is the more compatible choice. # support file uploading, so this is the more compatible choice.
def postData(self, http, method, fobj, vars, comp=6): def req(self, method, fobj=None, comp=6,
badAuthRaises=True, hkey=True):
bdry = "--"+MIME_BOUNDARY bdry = "--"+MIME_BOUNDARY
# write out post vars, including session key and compression flag
buf = StringIO() buf = StringIO()
vars = vars or {} # compression flag and session key as post vars
vars = {}
vars['c'] = 1 if comp else 0 vars['c'] = 1 if comp else 0
if hkey:
vars['k'] = self.hkey
for (key, value) in vars.items(): for (key, value) in vars.items():
buf.write(bdry + "\r\n") buf.write(bdry + "\r\n")
buf.write( buf.write(
'Content-Disposition: form-data; name="%s"\r\n\r\n%s\r\n' % 'Content-Disposition: form-data; name="%s"\r\n\r\n%s\r\n' %
(key, value)) (key, value))
# file header # payload as raw data or json
if fobj: if fobj:
# header
buf.write(bdry + "\r\n") buf.write(bdry + "\r\n")
buf.write("""\ buf.write("""\
Content-Disposition: form-data; name="data"; filename="data"\r\n\ Content-Disposition: form-data; name="data"; filename="data"\r\n\
@ -446,8 +451,12 @@ Content-Type: application/octet-stream\r\n\r\n""")
} }
body = buf.getvalue() body = buf.getvalue()
buf.close() buf.close()
resp, cont = http.request( resp, cont = self.con.request(
SYNC_URL+method, "POST", headers=headers, body=body) SYNC_URL+method, "POST", headers=headers, body=body)
if not badAuthRaises:
# return false if bad auth instead of raising
if resp['status'] == '403':
return False
self.assertOk(resp) self.assertOk(resp)
return cont return cont
@ -457,30 +466,27 @@ Content-Type: application/octet-stream\r\n\r\n""")
class RemoteServer(Syncer, HttpSyncer): class RemoteServer(Syncer, HttpSyncer):
def __init__(self, hkey): def __init__(self, hkey):
self.hkey = hkey HttpSyncer.__init__(self, hkey)
self.con = httpCon()
def hostKey(self, user, pw): def hostKey(self, user, pw):
"Returns hkey or none if user/pw incorrect." "Returns hkey or none if user/pw incorrect."
user = user.encode("utf-8") ret = self.req(
pw = pw.encode("utf-8") "hostKey", StringIO(simplejson.dumps(dict(u=user, p=pw))),
resp, cont = self.con.request( badAuthRaises=False, hkey=False)
SYNC_URL+"hostKey?" + urllib.urlencode(dict(u=user,p=pw))) if not ret:
if resp['status'] == '403':
# invalid auth # invalid auth
return return
self.assertOk(resp) self.hkey = simplejson.loads(ret)['key']
self.hkey = simplejson.loads(cont)['key']
return self.hkey return self.hkey
def meta(self): def meta(self):
resp, cont = self.con.request( ret = self.req(
SYNC_URL+"meta?" + urllib.urlencode(dict(k=self.hkey,v=SYNC_VER))) "meta", StringIO(simplejson.dumps(dict(v=SYNC_VER))),
if resp['status'] == '403': badAuthRaises=False)
# auth failure if not ret:
# invalid auth
return return
self.assertOk(resp) return simplejson.loads(ret)
return simplejson.loads(cont)
def applyChanges(self, **kw): def applyChanges(self, **kw):
return self._run("applyChanges", kw) return self._run("applyChanges", kw)
@ -499,8 +505,7 @@ class RemoteServer(Syncer, HttpSyncer):
def _run(self, cmd, data): def _run(self, cmd, data):
return simplejson.loads( return simplejson.loads(
self.postData(self.con, cmd, StringIO(simplejson.dumps(data)), self.req(cmd, StringIO(simplejson.dumps(data))))
self._vars()))
# Full syncing # Full syncing
########################################################################## ##########################################################################
@ -508,16 +513,13 @@ class RemoteServer(Syncer, HttpSyncer):
class FullSyncer(HttpSyncer): class FullSyncer(HttpSyncer):
def __init__(self, col, hkey, con): def __init__(self, col, hkey, con):
HttpSyncer.__init__(self, hkey, con)
self.col = col self.col = col
self.hkey = hkey
self.con = con
def download(self): def download(self):
runHook("sync", "download") runHook("sync", "download")
self.col.close() self.col.close()
resp, cont = self.con.request( cont = self.req("download")
SYNC_URL+"download?" + urllib.urlencode(self._vars()))
self.assertOk(resp)
tpath = self.col.path + ".tmp" tpath = self.col.path + ".tmp"
open(tpath, "wb").write(cont) open(tpath, "wb").write(cont)
# check the received file is ok # check the received file is ok
@ -532,8 +534,7 @@ class FullSyncer(HttpSyncer):
def upload(self): def upload(self):
runHook("sync", "upload") runHook("sync", "upload")
self.col.beforeUpload() self.col.beforeUpload()
assert self.postData(self.con, "upload", open(self.col.path, "rb"), assert self.req("upload", open(self.col.path, "rb")) == "OK"
self._vars()) == "OK"
# Media syncing # Media syncing
########################################################################## ##########################################################################
@ -610,34 +611,29 @@ Sanity check failed. Please copy and paste the text below:\n%s\n%s""" %
# Remote media syncing # Remote media syncing
########################################################################## ##########################################################################
class RemoteMediaServer(MediaSyncer, HttpSyncer): class RemoteMediaServer(HttpSyncer):
def __init__(self, hkey, con): def __init__(self, hkey, con):
self.hkey = hkey HttpSyncer.__init__(self, hkey, con)
self.con = con
def remove(self, **kw): def remove(self, **kw):
return simplejson.loads( return simplejson.loads(
self.postData( self.req("remove", StringIO(simplejson.dumps(kw))))
self.con, "remove", StringIO(simplejson.dumps(kw)),
self._vars()))
def files(self, **kw): def files(self, **kw):
return self.postData( return self.req("files", StringIO(simplejson.dumps(kw)))
self.con, "files", StringIO(simplejson.dumps(kw)), self._vars())
def addFiles(self, zip): def addFiles(self, zip):
# no compression, as we compress the zip file instead # no compression, as we compress the zip file instead
return simplejson.loads( return simplejson.loads(
self.postData(self.con, "addFiles", StringIO(zip), self.req("addFiles", StringIO(zip), comp=0))
self._vars(), comp=0))
def mediaSanity(self): def mediaSanity(self):
return simplejson.loads( return simplejson.loads(
self.postData(self.con, "mediaSanity", None, self._vars())) self.req("mediaSanity"))
# only for unit tests # only for unit tests
def mediatest(self, n): def mediatest(self, n):
return simplejson.loads( return simplejson.loads(
self.postData(self.con, "mediatest", StringIO( self.req("mediatest", StringIO(
simplejson.dumps(dict(n=n))), self._vars())) simplejson.dumps(dict(n=n)))))