THRIFT-438. py: Add support for Twisted.web in servers and clients

This patch adds a Twisted.web resource that can be used for processing incoming Thrift requests over HTTP

Patch: Esteve Fernandez

git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@939413 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/py/src/transport/TTwisted.py b/lib/py/src/transport/TTwisted.py
index a1ba150..b6dcb4e 100644
--- a/lib/py/src/transport/TTwisted.py
+++ b/lib/py/src/transport/TTwisted.py
@@ -22,7 +22,7 @@
 from twisted.internet import defer
 from twisted.protocols import basic
 from twisted.python import log
-
+from twisted.web import server, resource, http
 
 from thrift.transport import TTransport
 from cStringIO import StringIO
@@ -179,3 +179,41 @@
             self.oprot_factory)
         p.factory = self
         return p
+
+
+class ThriftResource(resource.Resource):
+
+    allowedMethods = ('POST',)
+
+    def __init__(self, processor, inputProtocolFactory,
+        outputProtocolFactory=None):
+        resource.Resource.__init__(self)
+        self.inputProtocolFactory = inputProtocolFactory
+        if outputProtocolFactory is None:
+            self.outputProtocolFactory = inputProtocolFactory
+        else:
+            self.outputProtocolFactory = outputProtocolFactory
+        self.processor = processor
+
+    def getChild(self, path, request):
+        return self
+
+    def _cbProcess(self, _, request, tmo):
+        msg = tmo.getvalue()
+        request.setResponseCode(http.OK)
+        request.setHeader("content-type", "application/x-thrift")
+        request.write(msg)
+        request.finish()
+
+    def render_POST(self, request):
+        request.content.seek(0, 0)
+        data = request.content.read()
+        tmi = TTransport.TMemoryBuffer(data)
+        tmo = TTransport.TMemoryBuffer()
+
+        iprot = self.inputProtocolFactory.getProtocol(tmi)
+        oprot = self.outputProtocolFactory.getProtocol(tmo)
+
+        d = self.processor.process(iprot, oprot)
+        d.addCallback(self._cbProcess, request, tmo)
+        return server.NOT_DONE_YET