source: ralphm-patches/disco-addressing.patch @ 53:fd2b3f70b221

Last change on this file since 53:fd2b3f70b221 was 53:fd2b3f70b221, checked in by Ralph Meijer <ralphm@…>, 9 years ago

Small cleanups for request handling.

File size: 9.8 KB
  • wokkel/disco.py

    # HG changeset patch
    # Parent 038fd78ebd5cdc8d25d00e4bc33a0c263eed277a
    Reimplement _DiscoRequest as generic.Request.
    
    Author: ralphm, Goffi.
    Fixes: #73.
    
    diff -r 038fd78ebd5c wokkel/disco.py
    a b  
    1414from twisted.words.protocols.jabber import error, jid
    1515from twisted.words.xish import domish
    1616
    17 from wokkel import data_form
    18 from wokkel.compat import IQ
     17from wokkel import data_form, generic
    1918from wokkel.iwokkel import IDisco
    2019from wokkel.subprotocols import IQHandlerMixin, XMPPHandler
    2120
     
    346345
    347346
    348347
    349 class _DiscoRequest(IQ):
     348class _DiscoRequest(generic.Request):
    350349    """
    351     Element representing an XMPP service discovery request.
     350    A Service Discovery request.
     351
     352    @ivar verb: Type of request: C{'info'} or C{'items'}.
     353    @type verb: C{str}
     354    @ivar nodeIdentifier: Optional node to request info for.
     355    @type nodeIdentifier: C{unicode}
    352356    """
    353357
    354     def __init__(self, xs, namespace, nodeIdentifier=''):
    355         """
    356         Initialize the request.
     358    verb = None
     359    nodeIdentifier = ''
    357360
    358         @param xs: XML Stream the request should go out on.
    359         @type xs: L{xmlstream.XmlStream}
    360         @param namespace: Request namespace.
    361         @type namespace: C{str}
    362         @param nodeIdentifier: Node to request info from.
    363         @type nodeIdentifier: C{unicode}
    364         """
    365         IQ.__init__(self, xs, "get")
    366         query = self.addElement((namespace, 'query'))
    367         if nodeIdentifier:
    368             query['node'] = nodeIdentifier
     361    _requestVerbMap = {
     362            NS_DISCO_INFO: 'info',
     363            NS_DISCO_ITEMS: 'items',
     364            }
     365
     366    _verbRequestMap = dict(((v, k) for k, v in _requestVerbMap.iteritems()))
     367
     368    def __init__(self, verb=None, nodeIdentifier='',
     369                       recipient=None, sender=None):
     370        generic.Request.__init__(self, recipient=recipient, sender=sender,
     371                                       stanzaType='get')
     372        self.verb = verb
     373        self.nodeIdentifier = nodeIdentifier
     374
     375
     376    def parseElement(self, element):
     377        generic.Request.parseElement(self, element)
     378
     379        verbElement = None
     380        for child in element.elements():
     381            if child.name == 'query' and child.uri in self._requestVerbMap:
     382                self.verb = self._requestVerbMap[child.uri]
     383                verbElement = child
     384
     385        if verbElement:
     386            self.nodeIdentifier = verbElement.getAttribute('node', '')
     387
     388
     389    def toElement(self):
     390        element = generic.Request.toElement(self)
     391
     392        childURI = self._verbRequestMap[self.verb]
     393        query = element.addElement((childURI, 'query'))
     394
     395        if self.nodeIdentifier:
     396            query['node'] = self.nodeIdentifier
     397
     398        return element
    369399
    370400
    371401
     
    388418        @type sender: L{jid.JID}
    389419        """
    390420
    391         request = _DiscoRequest(self.xmlstream, NS_DISCO_INFO, nodeIdentifier)
    392         if sender is not None:
    393             request['from'] = unicode(sender)
     421        request = _DiscoRequest('info', nodeIdentifier)
     422        request.sender = sender
     423        request.recipient = entity
    394424
    395         d = request.send(entity.full())
     425        d = self.request(request)
    396426        d.addCallback(lambda iq: DiscoInfo.fromElement(iq.query))
    397427        return d
    398428
     
    411441        @type sender: L{jid.JID}
    412442        """
    413443
    414         request = _DiscoRequest(self.xmlstream, NS_DISCO_ITEMS, nodeIdentifier)
    415         if sender is not None:
    416             request['from'] = unicode(sender)
     444        request = _DiscoRequest('items', nodeIdentifier)
     445        request.sender = sender
     446        request.recipient = entity
    417447
    418         d = request.send(entity.full())
     448        d = self.request(request)
    419449        d.addCallback(lambda iq: DiscoItems.fromElement(iq.query))
    420450        return d
    421451
     
    445475        @param iq: The request iq element.
    446476        @type iq: L{Element<twisted.words.xish.domish.Element>}
    447477        """
    448         requestor = jid.internJID(iq["from"])
    449         target = jid.internJID(iq["to"])
    450         nodeIdentifier = iq.query.getAttribute("node", '')
     478        request = _DiscoRequest.fromElement(iq)
    451479
    452480        def toResponse(info):
    453             if nodeIdentifier and not info:
     481            if request.nodeIdentifier and not info:
    454482                raise error.StanzaError('item-not-found')
    455483            else:
    456484                response = DiscoInfo()
    457                 response.nodeIdentifier = nodeIdentifier
     485                response.nodeIdentifier = request.nodeIdentifier
    458486
    459487                for item in info:
    460488                    response.append(item)
    461489
    462490            return response.toElement()
    463491
    464         d = self.info(requestor, target, nodeIdentifier)
     492        d = self.info(request.sender, request.recipient,
     493                      request.nodeIdentifier)
    465494        d.addCallback(toResponse)
    466495        return d
    467496
     
    473502        @param iq: The request iq element.
    474503        @type iq: L{Element<twisted.words.xish.domish.Element>}
    475504        """
    476         requestor = jid.internJID(iq["from"])
    477         target = jid.internJID(iq["to"])
    478         nodeIdentifier = iq.query.getAttribute("node", '')
     505        request = _DiscoRequest.fromElement(iq)
    479506
    480507        def toResponse(items):
    481508            response = DiscoItems()
    482             response.nodeIdentifier = nodeIdentifier
     509            response.nodeIdentifier = request.nodeIdentifier
    483510
    484511            for item in items:
    485512                response.append(item)
    486513
    487514            return response.toElement()
    488515
    489         d = self.items(requestor, target, nodeIdentifier)
     516        d = self.items(request.sender, request.recipient,
     517                       request.nodeIdentifier)
    490518        d.addCallback(toResponse)
    491519        return d
    492520
  • wokkel/generic.py

    diff -r 038fd78ebd5c wokkel/generic.py
    a b  
    2020except ImportError:
    2121    from wokkel.compat import BootstrapMixin
    2222
    23 from wokkel import disco
    2423from wokkel.iwokkel import IDisco
    2524from wokkel.subprotocols import XMPPHandler
    2625
     
    120119        info = set()
    121120
    122121        if not node:
     122            from wokkel import disco
    123123            info.add(disco.DiscoFeature(NS_VERSION))
    124124
    125125        return defer.succeed(info)
     
    174174    @type recipient: L{jid.JID}
    175175    """
    176176
     177    recipient = None
     178    sender = None
    177179    stanzaKind = None
    178180    stanzaID = None
    179181    stanzaType = None
  • wokkel/test/test_disco.py

    diff -r 038fd78ebd5c wokkel/test/test_disco.py
    a b  
    477477        Set up stub and protocol for testing.
    478478        """
    479479        self.stub = XmlStreamStub()
     480        self.patch(XMPPHandler, 'request', self.request)
    480481        self.protocol = disco.DiscoClientProtocol()
    481         self.protocol.xmlstream = self.stub.xmlstream
    482         self.protocol.connectionInitialized()
     482
     483
     484    def request(self, request):
     485        element = request.toElement()
     486        self.stub.xmlstream.send(element)
     487        return defer.Deferred()
    483488
    484489
    485490    def test_requestItems(self):
     
    511516        element = query.addElement(u'item')
    512517        element[u'jid'] = u"test2.example.org"
    513518
    514         self.stub.send(response)
     519        d.callback(response)
    515520        return d
    516521
    517522
     
    527532
    528533        response = toResponse(iq, u'result')
    529534        response.addElement((NS_DISCO_ITEMS, u'query'))
    530         self.stub.send(response)
    531535
     536        d.callback(response)
    532537        return d
    533538
    534539
     
    566571        element = query.addElement(u"feature")
    567572        element[u'var'] = u'http://jabber.org/protocol/muc'
    568573
    569         self.stub.send(response)
     574        d.callback(response)
    570575        return d
    571576
    572577
     
    575580        A disco info request can be sent with an explicit sender address.
    576581        """
    577582        d = self.protocol.requestInfo(JID(u'example.org'),
    578                                        sender=JID(u'test.example.org'))
     583                                      sender=JID(u'test.example.org'))
    579584
    580585        iq = self.stub.output[-1]
    581586        self.assertEqual(u'test.example.org', iq.getAttribute(u'from'))
    582587
    583588        response = toResponse(iq, u'result')
    584589        response.addElement((NS_DISCO_INFO, u'query'))
    585         self.stub.send(response)
    586590
     591        d.callback(response)
    587592        return d
    588593
    589594
     
    676681        return d
    677682
    678683
     684    def test_onDiscoInfoWithNoFromAttribute(self):
     685        """
     686        Disco info request without a from attribute has requestor None.
     687        """
     688        xml = """<iq to='example.com'
     689                     type='get'>
     690                   <query xmlns='%s'/>
     691                 </iq>""" % NS_DISCO_INFO
     692
     693        def info(requestor, target, nodeIdentifier):
     694            self.assertEqual(None, requestor)
     695
     696            return defer.succeed([
     697                disco.DiscoIdentity('dummy', 'generic', 'Generic Dummy Entity'),
     698                disco.DiscoFeature('jabber:iq:version')
     699            ])
     700
     701        self.service.info = info
     702        d = self.handleRequest(xml)
     703        return d
     704
     705
     706    def test_onDiscoInfoWithNoToAttribute(self):
     707        """
     708        Disco info request without a to attribute has target None.
     709        """
     710        xml = """<iq from='test@example.com'
     711                     type='get'>
     712                   <query xmlns='%s'/>
     713                 </iq>""" % NS_DISCO_INFO
     714
     715        def info(requestor, target, nodeIdentifier):
     716            self.assertEqual(JID('test@example.com'), requestor)
     717
     718            return defer.succeed([
     719                disco.DiscoIdentity('dummy', 'generic', 'Generic Dummy Entity'),
     720                disco.DiscoFeature('jabber:iq:version')
     721            ])
     722
     723        self.service.info = info
     724        d = self.handleRequest(xml)
     725        return d
     726
     727
    679728    def test_onDiscoInfoWithNode(self):
    680729        """
    681730        An info request for a node should return it in the response.
Note: See TracBrowser for help on using the repository browser.