2015-11-02 1 views
8

J'ai écrit une usine de serveur tcp de base, un client serveur et un service utilisant twisted. Le serveur tcp agit comme middleware entre un serveur django et un autre programme (appelons-le programme client).Impossible de faire une requête http au serveur django en utilisant twisted.web.AGENT

Ce que je veux réaliser -

1. client demande au serveur middleware tcp ;

2.it envoie une chaîne en tant que corps de requête;

3.le middleware Le serveur tcp désérialise les informations de la demande.

4. middleware fournit les informations sérialisées au serveur django.

5.Le serveur django répond alors au serveur middleware qui favorise la réponse au client après sérialisation la réponse.

Je suis capable d'atteindre jusqu'à l'étape 3, mais je suis incapable de faire une requête http au serveur django.

Ce qui suit est mon 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) 

Ce qui suit est 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 

Voici 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 

Permet de modifier le code avez supprimé qui dépendait tout autre code sans rapport avec le problème.

+0

Pouvez-vous essayer de réduire cela en un http://sscce.org? Il y a beaucoup de code manquant ici, donc je ne peux pas essayer d'exécuter votre exemple. Pour ce que ça vaut, la présence de Django sur le backend ne fait pas de différence ici: c'est juste Twisted qui fait une requête HTTP. Comme vous l'avez identifié, cela fonctionne de manière isolée, donc une interaction complexe avec le reste de votre système cause des problèmes, et sans voir le reste de votre système dans son intégralité, je ne peux pas dire de quoi il s'agit. (Essayer de déboguer votre système * entier * n'est vraiment utile à personne d'autre, donc plus vous pouvez l'affiner, mieux c'est.) – Glyph

Répondre

0

J'ai trouvé le bogue. Ci-dessous le code corrigé.

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) 
+0

Ce code est une erreur de syntaxe, donc je ne suis pas sûr que tout soit corrigé:). Je pense que vous pouvez éliminer 'self.data' entièrement? – Glyph