Unable to make http request to django server using twisted.web.client.AGENT

Akshat Tripathi vmt.eiz at gmail.com
Fri Nov 13 07:23:41 EST 2015


On Thursday, 5 November 2015 13:06:13 UTC+5:30, Akshat Tripathi  wrote:
> I have written a basic tcp server factory, server client and a service using twisted. The tcp server acts as the middleware between a django server and an another program (let's call it client program).
> 
> What I want to achieve -
> 
> 1.client requests the middleware tcp server;
> 
> 2.it sends a string as the request body;
> 
> 3.the middleware tcp server deserializes information from the request.
> 
> 4.middleware furthers the serialized information to the django server.
> 
> 5.The django server then responds to the middleware server which furthers the response to the client after serializing the response.
> 
> I am able to reach till step 3, but am unable to make any http request to the django server.
> 
> 
> 
> 
> The following is my middleware.py
> 
> from twisted.internet.protocol import ServerFactory
> from twisted.internet.protocol import Protocol
> 
> from test_service import MyService
> 
> 
> class TCPServerProtocol(Protocol):
>     data = ''
> 
>     def connectionMade(self):
>         self.deferred = self.factory.service.deferred
>         self.deferred.addCallback(self.factory.service.s)
>         self.deferred.addCallback(self.transport.write)
>         self.deferred.addBoth(lambda r: self.transport.loseConnection)
> 
>     def dataReceived(self, data):
>         self.data += data
> 
>     def connectionLost(self, reason):
>         self.forward(self.data)
> 
>     def forward(self, data):
>         if self.deferred is not None:
>             d, self.deferred = self.deferred, None
>             d.callback(data)
> 
> class TCPServerFactory(ServerFactory):
> 
>     protocol = TCPServerProtocol
> 
>     def __init__(self, service):
>         self.service = service
> 
> def runserver(ip, port):
>     iface =  {'home': '192.168.0.104', 'work': '127.0.0.1'}
>     service = MyService()
>     factory = TCPServerFactory(service)
>     from twisted.internet import reactor
>     reactor.listenTCP(port=port, factory=factory, interface=iface[ip])
>     reactor.run()
> 
> if __name__ == '__main__':
>     import sys
>     ip = sys.argv[1]
>     port = int(sys.argv[2])
>     runserver(ip, port)
> 
> 
> 
> 
> The following is test_service.py
> 
> from twisted.internet.defer import Deferred
> 
> from test_http_client import HTTPClientFactory
> 
> class MyService(object):
>     def __init__(self):
>         self.deferred = Deferred()
> 
>     def s(self, data):
>         kwargs = {}
>         kwargs['url'] = b'http://127.0.0.1:8000/some/end/point'
>         kwargs['url'] = kwargs['url'].encode('latin-1')
>         kwargs['method'] = 'POST'
>         kwargs['data'] = data
> 
>         client = HTTPClientFactory(**kwargs)
>         d = client.deferred
>         return d
> 
> 
> The following is test_http_client.py
> 
> from StringIO import StringIO
> import json
> 
> from twisted.internet.protocol import Protocol
> from twisted.internet.defer import Deferred
> from twisted.web.client import Agent, FileBodyProducer
> from twisted.web.http_headers import Headers
> 
> 
> class HTTPClientProtocol(Protocol):
>     def __init__(self, finished):
>         self.finished = finished
>         self.data = ''
> 
>     def dataReceived(self, data):
>         print '----------Data Received by HTTPClientProtocol----------'
>         print data
>         self.data += data
> 
>     def connectionLost(self, reason):
>         print '----------HTTP Client connection Lost----------'
>         print reason.getErrorMessage()
>         if self.finished is not None:
>             print 'finished is not None'
>             f, self.finished = self.finished, None
>             f.callback(self.data)
> 
> class HTTPClientFactory(object):
> 
>     """
>     Class handling communication with HTTP server.
>     """
> 
>     def __init__(self, **kwargs):
>         data = kwargs['data'] 
>         try:
>             body = FileBodyProducer(StringIO(json.dumps(data)))
>             print '----------Request body object created----------'
>         except Exception as e:
>             print '----------Request body object creation FAILURE----------'
>             print e
>             return e  
>         url = kwargs.get('url', None)
>         method = kwargs.get('method', None)
> 
>         from twisted.internet import reactor
>         agent = Agent(reactor)
>         if not data:
>             body = None
> 
>         self.deferred = agent.request(method,
>                                     url,
>                                     Headers({'Content-Type': ['application/json']}),
>                                     bodyProducer=body)
> 
>         self.deferred.addCallback(self.get_response)
> 
>     def get_response(self, response):
>         print 'Response received'
>         finished = Deferred()
>         response.deliverBody(HTTPClientProtocol(finished))
>         return finished

Found the bug. Below is the corrected code.

class TCPServerProtocol(Protocol):

    # data = ''

    def connectionMade(self):
        self.deferred = self.factory.service.deferred
        self.deferred.addCallback(self.factory.service.s)
        self.deferred.addCallback(self.transport.write)
        self.deferred.addBoth(lambda r: self.transport.loseConnection)

    def dataReceived(self, data):
        self.data = data           # instead of self.data += data
        self.forward(self.data)    # this is the right place to call this method which in turn fires the callback through which the request is made to the server.

    def connectionLost(self, reason): pass
        # this will not be called until the connection from client is ended. 
        # self.forward(self.data)

    def forward(self, data):
        if self.deferred is not None:
            d, self.deferred = self.deferred, None
            d.callback(data)



More information about the Python-list mailing list