Skip to content

Instantly share code, notes, and snippets.

@rndmcnlly
Created December 6, 2009 23:25
Show Gist options
  • Save rndmcnlly/250492 to your computer and use it in GitHub Desktop.
Save rndmcnlly/250492 to your computer and use it in GitHub Desktop.
#!/usr/bin/python
from __future__ import with_statement
import base64
import PyV8
import time
from twisted.application import service, internet
from twisted.web import server, resource, client
from twisted.internet import threads
from urllib import unquote
class Rapper(object):
def __init__(self, wrapped):
self.__dict__ = wrapped
class Gistlets(resource.Resource):
def getChild(self, path, request):
return Gistlet(path)
class Gistlet(resource.Resource):
isLeaf = True
def __init__(self, which):
resource.Resource.__init__(self)
self.which = which
def render(self, request):
def gotCode(code):
env = Rapper(buildJSGIEvironment(request))
threads.deferToThread(run,code,env).addCallbacks(gotResponse,failed)
def gotResponse(response):
print 'gotResponse'
try:
request.setResponseCode(response['status'])
for (k,v) in response['headers'].items():
request.setHeader(k,v)
request.write(response['body'])
except Exception:
import traceback
traceback.print_exc()
finally:
request.finish()
def failed(why):
print 'failed:'
print why
request.setResponseCode(500)
request.write('failed to fetch gist: '+str(why))
request.finish()
client.getPage("http://gist.github.com/%s.txt" %
self.which).addCallbacks(gotCode, failed)
return server.NOT_DONE_YET
def run(code,env):
tid = PyV8.JSEngine.currentThreadId
print 'worktherad', tid
def expire():
raise Exception("time's up!")
import threading
watchdog = threading.Timer(5, expire)
watchdog.start()
with PyV8.JSContext(Globals()) as context:
context.eval(code)
local_response = context.locals.app(env)
response = dict()
response['status'] = local_response.status
response['headers'] = PyV8.convert(local_response.headers)
response['body'] = str(local_response.body)
watchdog.cancel()
return response
def buildJSGIEvironment(request):
if request.prepath:
scriptName = '/' + '/'.join(request.prepath)
else:
scriptName = ''
if request.postpath:
pathInfo = '/' + '/'.join(request.postpath)
else:
pathInfo = ''
parts = request.uri.split('?', 1)
if len(parts) == 1:
queryString = ''
else:
queryString = unquote(parts[1])
environ = {
'REQUEST_METHOD': request.method,
'REMOTE_ADDR': request.getClientIP(),
'SCRIPT_NAME': scriptName,
'PATH_INFO': pathInfo,
'QUERY_STRING': queryString,
'CONTENT_TYPE': request.getHeader('content-type') or '',
'CONTENT_LENGTH': request.getHeader('content-length') or '',
'SERVER_NAME': request.getRequestHostname(),
'SERVER_PORT': str(request.getHost().port),
'SERVER_PROTOCOL': request.clientproto}
for name, values in request.requestHeaders.getAllRawHeaders():
name = 'HTTP_' + name.upper().replace('-', '_')
# It might be preferable for http.HTTPChannel to clear out
# newlines.
environ[name] = ','.join([
v.replace('\n', ' ') for v in values])
return environ
class Globals(PyV8.JSClass):
def sleep(self, seconds):
print 'tid', PyV8.JSEngine.currentThreadId
import time
time.sleep(seconds)
def log(self,str):
print str
def fetch(self,url):
import urllib
print 'fetching url', url, type(url)
f = urllib.urlopen(str(url))
page = f.read()
f.close()
print 'got page', page
return page
root = resource.Resource()
root.putChild('gistlets', Gistlets())
port = 8124
application = service.Application("gistlets")
service = internet.TCPServer(port, server.Site(root))
service.setServiceParent(application)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment