A place for things I don't want to forget

Wednesday, October 28, 2009

take #2


from twisted.web import server, xmlrpc, http
from twisted.web.server import Site
from twisted.web.static import File
from twisted.web.resource import Resource
from twisted.internet.task import deferLater
from twisted.enterprise import adbapi
from twisted.internet import reactor, threads, defer



import sys
import time
import random
import hashlib
import memcache

def sendToThread(kwargs):
''' this is a convenience method that will be used to run blocking
methods in a thread. That way twisted will not block waiting for them.
It takes a dictionary as a parameter. This dictionary is REQUIRED to have
key,values for a) func, b) cb, c) err_cb (function to run, callback and
error callback).

Also for each of these keys it looks for X_args and X_kwargs (where X
is one of a),b),c) above.
It returns the deferred object.
'''

func = kwargs['func']
func_args = kwargs.get('func_args', ())
func_kwargs = kwargs.get('func_kwargs', {})

cb = kwargs['cb']
cb_args = kwargs.get('cb_args', ())
cb_kwargs = kwargs.get('cb_kwargs', {})

err_cb = kwargs['err_cb']
err_cb_args = kwargs.get('err_cb_args', ())
err_cb_kwargs = kwargs.get('err_db_kwargs', {})
d = threads.deferToThread(func, *func_args, **func_kwargs)
d.addCallback(cb, *cb_args, **cb_kwargs)
d.addErrback(err_cb, *err_cb_args, **err_cb_kwargs)

return d

class CodeHandler(Resource):
def __init__(self, path):
self.children = {}
self.path = path

def authRequest(self, request):
'''
This method should authorize incoming requests for code download.
It should return a deferred object and the callback should either
do all the magic stuff or send a 403 back

For now let's just return true/false.
'''
res = request.getHeader('lol')
if (res == '1234'):
return (True, 'OK')
else:
return (False, '''Just because I don't like you''')

def calcSig(self, path, request):
val = mc.get(path)
print val
if not val:
hash = hashlib.sha1()
f = open(path, 'r')
hash.update(f.read())
f.close()
h = hash.hexdigest()
mc.set(path,h)
else:
h = val
request.setHeader('sig',h)
return (request, path)


def putResults(self, parms):
request = parms[0]
path = parms[1]
return File(path).render(request)

def _catchFail(self, err):
''' cleanup stuff in case connection is closed on us goes here '''
print "client disconnected: %s" % err

def genericFail(self, *args):
args[0].printDetailedTraceback()

def render(self, request):
self.id = random.random()
ret = self.authRequest(request)
if ret[0]:
if request.getHeader('sleep'):
dfrdict = {'func':self.calcSig,
'cb': self.putResults,
'err_cb': self.genericFail,
'func_args': [self.path, request]}
d = sendToThread(dfrdict)
request.notifyFinish().addErrback(self._catchFail)
return server.NOT_DONE_YET
request.setHeader('omg', 'hi')
return File(self.path).render(request)
else:
request.setResponseCode(http.FORBIDDEN)
return "

Access Denied


%s" % ret[1]

def getChild(self, path, request):
return self

if __name__ == '__main__':
mc = memcache.Client(['127.0.0.1:11211'], debug=0)
root = Resource()
#root.putChild('RPC2', TestRPC())
root.putChild('modules', CodeHandler('/tmp/lol.sql3'))
factory = Site(root)
dbpool = adbapi.ConnectionPool('sqlite3','/tmp/lol.sql3')
reactor.listenTCP(8888, factory)
reactor.run()