Created
December 6, 2009 23:25
-
-
Save rndmcnlly/250492 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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