Mercurial > libervia-backend
comparison sat/plugins/plugin_xep_0363.py @ 3526:e84ffb48acd4
plugin XEP-0363: allow async callbacks in handlers + method to generate `file-too-large` element
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 05 May 2021 15:37:33 +0200 |
parents | be6d91572633 |
children | 0ff265725489 |
comparison
equal
deleted
inserted
replaced
3525:7f5bf108961a | 3526:e84ffb48acd4 |
---|---|
22 from dataclasses import dataclass | 22 from dataclasses import dataclass |
23 from urllib import parse | 23 from urllib import parse |
24 from wokkel import disco, iwokkel | 24 from wokkel import disco, iwokkel |
25 from zope.interface import implementer | 25 from zope.interface import implementer |
26 from twisted.words.protocols.jabber import jid, xmlstream, error | 26 from twisted.words.protocols.jabber import jid, xmlstream, error |
27 from twisted.words.xish import domish | |
27 from twisted.internet import reactor | 28 from twisted.internet import reactor |
28 from twisted.internet import defer | 29 from twisted.internet import defer |
29 from twisted.web import client as http_client | 30 from twisted.web import client as http_client |
30 from twisted.web import http_headers | 31 from twisted.web import http_headers |
31 from sat.core.i18n import _ | 32 from sat.core.i18n import _ |
32 from sat.core.xmpp import SatXMPPComponent | 33 from sat.core.xmpp import SatXMPPComponent |
33 from sat.core.constants import Const as C | 34 from sat.core.constants import Const as C |
34 from sat.core.log import getLogger | 35 from sat.core.log import getLogger |
35 from sat.core import exceptions | 36 from sat.core import exceptions |
36 from sat.tools import web as sat_web | 37 from sat.tools import web as sat_web, utils |
37 | 38 |
38 | 39 |
39 log = getLogger(__name__) | 40 log = getLogger(__name__) |
40 | 41 |
41 PLUGIN_INFO = { | 42 PLUGIN_INFO = { |
120 assert callback not in self.handlers | 121 assert callback not in self.handlers |
121 req_handler = RequestHandler(callback, priority) | 122 req_handler = RequestHandler(callback, priority) |
122 self.handlers.append(req_handler) | 123 self.handlers.append(req_handler) |
123 self.handlers.sort(key=lambda handler: handler.priority, reverse=True) | 124 self.handlers.sort(key=lambda handler: handler.priority, reverse=True) |
124 | 125 |
126 def getFileTooLargeElt(self, max_size: int) -> domish.Element: | |
127 """Generate <file-too-large> app condition for errors""" | |
128 file_too_large_elt = domish.Element((NS_HTTP_UPLOAD, "file-too-large")) | |
129 file_too_large_elt.addElement("max-file-size", str(max_size)) | |
130 return file_too_large_elt | |
131 | |
125 async def getHTTPUploadEntity(self, client, upload_jid=None): | 132 async def getHTTPUploadEntity(self, client, upload_jid=None): |
126 """Get HTTP upload capable entity | 133 """Get HTTP upload capable entity |
127 | 134 |
128 upload_jid is checked, then its components | 135 upload_jid is checked, then its components |
129 @param upload_jid(None, jid.JID): entity to check | 136 @param upload_jid(None, jid.JID): entity to check |
354 | 361 |
355 # component | 362 # component |
356 | 363 |
357 def onComponentRequest(self, iq_elt, client): | 364 def onComponentRequest(self, iq_elt, client): |
358 iq_elt.handled=True | 365 iq_elt.handled=True |
366 defer.ensureDeferred(self.handleComponentRequest(client, iq_elt)) | |
367 | |
368 async def handleComponentRequest(self, client, iq_elt): | |
359 try: | 369 try: |
360 request_elt = next(iq_elt.elements(NS_HTTP_UPLOAD, "request")) | 370 request_elt = next(iq_elt.elements(NS_HTTP_UPLOAD, "request")) |
361 request = UploadRequest( | 371 request = UploadRequest( |
362 from_=jid.JID(iq_elt['from']), | 372 from_=jid.JID(iq_elt['from']), |
363 filename=parse.quote(request_elt['filename'].replace('/', '_'), safe=''), | 373 filename=parse.quote(request_elt['filename'].replace('/', '_'), safe=''), |
370 | 380 |
371 err = None | 381 err = None |
372 | 382 |
373 for handler in self.handlers: | 383 for handler in self.handlers: |
374 try: | 384 try: |
375 slot = handler.callback(client, request) | 385 slot = await utils.asDeferred(handler.callback, client, request) |
376 except error.StanzaError as e: | 386 except error.StanzaError as e: |
377 log.warning( | 387 log.warning( |
378 "a stanza error has been raised while processing HTTP Upload of " | 388 "a stanza error has been raised while processing HTTP Upload of " |
379 f"request: {e}" | 389 f"request: {e}" |
380 ) | 390 ) |
387 break | 397 break |
388 else: | 398 else: |
389 log.warning( | 399 log.warning( |
390 _("no service can handle HTTP Upload request: {elt}") | 400 _("no service can handle HTTP Upload request: {elt}") |
391 .format(elt=iq_elt.toXml())) | 401 .format(elt=iq_elt.toXml())) |
392 if err is not None: | 402 if err is None: |
393 condition = err.condition | 403 err = error.StanzaError("feature-not-implemented") |
394 else: | 404 client.send(err.toResponse(iq_elt)) |
395 condition = "feature-not-implemented" | |
396 client.sendError(iq_elt, condition) | |
397 return | 405 return |
398 | 406 |
399 iq_result_elt = xmlstream.toResponse(iq_elt, "result") | 407 iq_result_elt = xmlstream.toResponse(iq_elt, "result") |
400 slot_elt = iq_result_elt.addElement((NS_HTTP_UPLOAD, 'slot')) | 408 slot_elt = iq_result_elt.addElement((NS_HTTP_UPLOAD, 'slot')) |
401 put_elt = slot_elt.addElement('put') | 409 put_elt = slot_elt.addElement('put') |