From 1a331b77bdf426cd2d2a0d060881b9b8bb7ab2bf Mon Sep 17 00:00:00 2001 From: dgtlmoon Date: Tue, 29 Nov 2022 12:45:46 +0100 Subject: [PATCH] Faster BrowserStep screenshot updates and enable gzip compression for all content replies in the UI --- changedetectionio/__init__.py | 5 +++++ .../blueprint/browser_steps/__init__.py | 21 +++++++++++++++---- requirements.txt | 1 + 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/changedetectionio/__init__.py b/changedetectionio/__init__.py index dceefcc6..5d22a280 100644 --- a/changedetectionio/__init__.py +++ b/changedetectionio/__init__.py @@ -27,6 +27,7 @@ from flask import ( session, url_for, ) +from flask_compress import Compress as FlaskCompress from flask_login import login_required from flask_restful import abort, Api from flask_wtf import CSRFProtect @@ -51,6 +52,10 @@ app = Flask(__name__, static_url_path="", static_folder="static", template_folder="templates") +from flask_compress import Compress + +# Super handy for compressing large BrowserSteps responses and others +FlaskCompress(app) # Stop browser caching of assets app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 0 diff --git a/changedetectionio/blueprint/browser_steps/__init__.py b/changedetectionio/blueprint/browser_steps/__init__.py index b877a20f..209d6d23 100644 --- a/changedetectionio/blueprint/browser_steps/__init__.py +++ b/changedetectionio/blueprint/browser_steps/__init__.py @@ -210,16 +210,29 @@ def construct_blueprint(datastore: ChangeDetectionStore): except playwright._impl._api_types.Error as e: return make_response("Browser session ran out of time :( Please reload this page."+str(e), 401) - p = {'screenshot': "data:image/png;base64,{}".format( + # Use send_file() which is way faster than read/write loop on bytes + import json + from tempfile import mkstemp + from flask import send_file + tmp_fd, tmp_file = mkstemp(text=True, suffix=".json", prefix="changedetectionio-") + + output = json.dumps({'screenshot': "data:image/png;base64,{}".format( base64.b64encode(state[0]).decode('ascii')), 'xpath_data': state[1], 'session_age_start': this_session.age_start, 'browser_time_remaining': round(remaining) - } + }) + + with os.fdopen(tmp_fd, 'w') as f: + f.write(output) + response = make_response(send_file(path_or_file=tmp_file, + mimetype='application/json; charset=UTF-8', + etag=True)) + # No longer needed + os.unlink(tmp_file) - # @todo BSON/binary JSON, faster xfer, OR pick it off the disk - return p + return response return browser_steps_blueprint diff --git a/requirements.txt b/requirements.txt index a10f3d0f..c1534fd4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,6 @@ flask~=2.0 flask_wtf +flask-compress eventlet>=0.31.0 validators timeago~=1.0