mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-09-06 13:41:28 +00:00
120 lines
3.9 KiB
Python
120 lines
3.9 KiB
Python
from twisted.internet import defer, protocol, reactor
|
|
from twisted.protocols import basic
|
|
from twisted.web2 import server, http, resource, responsecode, stream, channel
|
|
from twisted.application import service, strports
|
|
|
|
import struct
|
|
|
|
|
|
class uWSGIClientResource(resource.LeafResource):
|
|
|
|
def __init__(self,app='', port=3030, host='localhost'):
|
|
resource.LeafResource.__init__(self)
|
|
self.host = host
|
|
self.port = port
|
|
self.app = app
|
|
|
|
def renderHTTP(self, request):
|
|
return uWSGI(request, self.app, self.host, self.port)
|
|
|
|
def uWSGI(request, app, host, port):
|
|
if request.stream.length is None:
|
|
return http.Response(responsecode.LENGTH_REQUIRED)
|
|
|
|
request.uwsgi_app = app
|
|
factory = uWSGIClientProtocolFactory(request)
|
|
reactor.connectTCP(host, port, factory)
|
|
return factory.deferred
|
|
|
|
class uWSGIClientProtocol(basic.LineReceiver):
|
|
|
|
def __init__(self, request, deferred):
|
|
self.request = request
|
|
self.deferred = deferred
|
|
self.stream = stream.ProducerStream()
|
|
self.response = http.Response(stream=self.stream)
|
|
self.status_parsed = None
|
|
|
|
def build_uwsgi_var(self,key,value):
|
|
return struct.pack('<H',len(key)) + key + struct.pack('<H',len(value)) + value
|
|
|
|
def connectionMade(self):
|
|
print self.request.__dict__
|
|
# reset response parser
|
|
self.status_parsed = None
|
|
# build header and vars
|
|
vars = ''
|
|
|
|
if self.request.stream.length:
|
|
vars += self.build_uwsgi_var('CONTENT_LENGTH',str(self.request.stream.length))
|
|
|
|
for hkey, hval in self.request.headers.getAllRawHeaders():
|
|
# use a list, probably it will be extended
|
|
if hkey.lower() not in ('content-type'):
|
|
vars += self.build_uwsgi_var('HTTP_'+hkey.upper().replace('-','_'),','.join(hval))
|
|
else:
|
|
vars += self.build_uwsgi_var(hkey.upper().replace('-','_'),','.join(hval))
|
|
|
|
|
|
vars += self.build_uwsgi_var('REQUEST_METHOD', self.request.method)
|
|
vars += self.build_uwsgi_var('SCRIPT_NAME', self.request.uwsgi_app)
|
|
vars += self.build_uwsgi_var('PATH_INFO', self.request.path[len(self.request.uwsgi_app):])
|
|
vars += self.build_uwsgi_var('QUERY_STRING', self.request.querystring)
|
|
vars += self.build_uwsgi_var('SERVER_NAME', self.request.host)
|
|
vars += self.build_uwsgi_var('SERVER_PORT', str(self.request.port))
|
|
vars += self.build_uwsgi_var('SERVER_PROTOCOL', self.request.scheme.upper()+'/'+str(self.request.clientproto[0]) +'.'+str(self.request.clientproto[1]))
|
|
|
|
vars += self.build_uwsgi_var('REQUEST_URI', self.request.uri)
|
|
vars += self.build_uwsgi_var('REMOTE_ADDR', self.request.remoteAddr.host)
|
|
|
|
|
|
self.transport.write(struct.pack('<BHB',0, len(vars),0))
|
|
self.transport.write(vars)
|
|
|
|
# send request data
|
|
stream.StreamProducer(self.request.stream).beginProducing(self.transport)
|
|
|
|
def lineReceived(self, line):
|
|
if self.status_parsed is None:
|
|
self.response.code = line.split(' ',2)[1]
|
|
self.status_parsed = True
|
|
return
|
|
|
|
# end of headers
|
|
if line == '':
|
|
self.setRawMode()
|
|
self.deferred.callback(self.response)
|
|
self.response = None
|
|
return
|
|
|
|
name, value = line.split(':',1)
|
|
value = value.strip()
|
|
|
|
self.response.headers.addRawHeader(name, value)
|
|
|
|
def rawDataReceived(self, data):
|
|
self.stream.write(data)
|
|
|
|
def connectionLost(self, reason):
|
|
self.stream.finish()
|
|
|
|
|
|
class uWSGIClientProtocolFactory(protocol.ClientFactory):
|
|
|
|
protocol = uWSGIClientProtocol
|
|
noisy = False # Make Factory shut up
|
|
|
|
def __init__(self, request):
|
|
self.request = request
|
|
self.deferred = defer.Deferred()
|
|
|
|
def buildProtocol(self, addr):
|
|
return self.protocol(self.request, self.deferred)
|
|
|
|
def clientConnectionFailed(self, connector, reason):
|
|
self.sendFailureResponse(reason)
|
|
|
|
def sendFailureResponse(self, reason):
|
|
response = http.Response(code=responsecode.BAD_GATEWAY, stream=str(reason.value))
|
|
self.deferred.callback(response)
|