Welcome to mirror list, hosted at ThFree Co, Russian Federation.

dev.gajim.org/gajim/python-nbxmpp.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Hörist <philipp@hoerist.com>2023-05-18 20:48:10 +0300
committerPhilipp Hörist <philipp@hoerist.com>2023-05-19 10:16:25 +0300
commit293480a8fb62edacea81b6322b731cbc78ffb163 (patch)
tree58854629caa8e1137426e96051089f8a68e9c49a
parent6ce7136ba4221de9afd34948145b4420ef519dfb (diff)
imprv: Use got-body-data for determining progress
Fixes #143
-rw-r--r--nbxmpp/http.py63
-rw-r--r--test/unit/test_http.py10
2 files changed, 47 insertions, 26 deletions
diff --git a/nbxmpp/http.py b/nbxmpp/http.py
index 9ac245c..1a9ca70 100644
--- a/nbxmpp/http.py
+++ b/nbxmpp/http.py
@@ -50,7 +50,7 @@ HTTP_METHODS_T = Literal[
CHUNK_SIZE = 32768
DEFAULT_USER_AGENT = f'nbxmpp/{nbxmpp.__version__}'
SIGNAL_ACTIONS = GObject.SignalFlags.RUN_LAST | GObject.SignalFlags.ACTION
-
+MIN_SOUP_3_4 = Soup.check_version(3, 4, 0)
class HTTPLogAdapter(logging.LoggerAdapter):
def process(self, msg: str, kwargs: Any) -> tuple[str, Any]:
@@ -278,6 +278,10 @@ class HTTPRequest(GObject.GObject):
self._message.connect('got-body', self._on_got_body)
self._message.connect('restarted', self._on_restarted)
self._message.connect('finished', self._on_finished)
+ self._message.connect('got-headers', self._on_got_headers)
+
+ if MIN_SOUP_3_4:
+ self._message.connect('got-body-data', self._on_got_body_data)
soup_session = self._session.get_soup_session()
soup_session.send_async(self._message,
@@ -360,11 +364,9 @@ class HTTPRequest(GObject.GObject):
self._finish_read()
return
- length = len(bytes_)
- self._received_size += length
- if self._received_size > self._response_content_length:
- self._finish_read(HTTPRequestError.CONTENT_OVERFLOW)
- return
+ if not MIN_SOUP_3_4:
+ self._received_size += len(bytes_)
+ self._check_content_overflow()
if self._output_stream is None:
self._response_body_data += bytes_
@@ -383,11 +385,8 @@ class HTTPRequest(GObject.GObject):
self._read_async()
- if (self._emit_response_progress and
- self._message.get_method() == 'GET'):
- self.emit('response-progress',
- self._received_size / self._response_content_length)
-
+ if not MIN_SOUP_3_4:
+ self._emit_progress()
def _finish_read(self, error: Optional[HTTPRequestError] = None) -> None:
self._log.info('Finished reading')
@@ -404,11 +403,7 @@ class HTTPRequest(GObject.GObject):
) -> None:
# Signal is only raised when there is content in the response
-
headers = message.get_response_headers()
-
- self._response_content_length = headers.get_content_length()
-
if content_type is None:
# According to the docs, content_type is None when the sniffer
# decides to trust the content-type sent by the server.
@@ -416,14 +411,19 @@ class HTTPRequest(GObject.GObject):
self._response_content_type = content_type or ''
- self._log.info('Sniffed: content-type: %s, content-length: %s',
- self._response_content_type,
- self._response_content_length)
+ self._log.info('Sniffed: content-type: %s',
+ self._response_content_type)
self.emit('content-sniffed',
self._response_content_length,
self._response_content_type)
+ def _on_got_headers(self, message: Soup.Message) -> None:
+ headers = message.get_response_headers()
+ self._response_content_length = headers.get_content_length()
+ self._log.info('Got Headers: content-length: %s',
+ self._response_content_length)
+
def _on_got_body(self, _message: Soup.Message) -> None:
# This signal tells us that the full body was received.
# The `finished` signal is not a sure indicator if the message body
@@ -432,11 +432,38 @@ class HTTPRequest(GObject.GObject):
self._log.info('Body received')
self._body_received = True
+ def _on_got_body_data(self,
+ _message: Soup.Message,
+ chunk_size: int
+ ) -> None:
+
+ self._received_size += chunk_size
+ self._check_content_overflow()
+
+ status = self._message.get_status()
+ if status in (Soup.Status.OK, Soup.Status.CREATED):
+ self._emit_progress()
+
+ def _emit_progress(self) -> None:
+ if not self._emit_response_progress:
+ return
+
+ if not self._message.get_method() == 'GET':
+ return
+
+ self.emit('response-progress',
+ self._received_size / self._response_content_length)
+
+ def _check_content_overflow(self) -> None:
+ if self._received_size > self._response_content_length:
+ self._finish_read(HTTPRequestError.CONTENT_OVERFLOW)
+
def _on_restarted(self, _message: Soup.Message) -> None:
self._log.info('Restarted')
self._body_received = False
self._response_content_type = ''
self._response_content_length = 0
+ self._received_size = 0
def _on_finished(self, _message: Soup.Message) -> None:
self._log.info('Message finished')
diff --git a/test/unit/test_http.py b/test/unit/test_http.py
index da63c94..6ada805 100644
--- a/test/unit/test_http.py
+++ b/test/unit/test_http.py
@@ -1,9 +1,6 @@
-from time import time
import tempfile
import unittest
-from unittest.mock import call
from unittest.mock import Mock
-from unittest.mock import patch
import os
from pathlib import Path
@@ -124,13 +121,11 @@ class HTTP(unittest.TestCase):
session = HTTPSession()
request = session.create_request()
- def _on_progress(req, progress):
- self.assertIsInstance(progress, float)
+ def _on_start(req):
req.cancel()
callback_mock = Mock()
- request.connect('starting-response-body', callback_mock.starting)
- request.connect('response-progress', _on_progress)
+ request.connect('starting-response-body', _on_start)
request.connect('finished', callback_mock.finished)
request.connect('destroy', lambda *args: mainloop.quit())
request.send('GET', LARGE_FILE_URL, timeout=10)
@@ -141,7 +136,6 @@ class HTTP(unittest.TestCase):
self.assertTrue(request.is_finished())
self.assertEqual(request.get_error(), HTTPRequestError.CANCELLED)
- callback_mock.starting.assert_called()
callback_mock.finished.assert_called()
def test_download_failed_404(self):