summaryrefslogtreecommitdiff
path: root/searx/webapp.py
diff options
context:
space:
mode:
Diffstat (limited to 'searx/webapp.py')
-rwxr-xr-xsearx/webapp.py130
1 files changed, 95 insertions, 35 deletions
diff --git a/searx/webapp.py b/searx/webapp.py
index 23c5d70cc..4ecaab7d2 100755
--- a/searx/webapp.py
+++ b/searx/webapp.py
@@ -6,6 +6,7 @@
# pylint: disable=use-dict-literal
from __future__ import annotations
+import inspect
import hashlib
import hmac
import json
@@ -29,6 +30,8 @@ from pygments import highlight
from pygments.lexers import get_lexer_by_name
from pygments.formatters import HtmlFormatter # pylint: disable=no-name-in-module
+from werkzeug.serving import is_running_from_reloader
+
import flask
from flask import (
@@ -48,12 +51,12 @@ from flask_babel import (
format_decimal,
)
+import searx
from searx.extended_types import sxng_request
from searx import (
logger,
get_setting,
settings,
- searx_debug,
)
from searx import infopage
@@ -81,7 +84,6 @@ from searx.webutils import (
exception_classname_to_text,
new_hmac,
is_hmac_of,
- is_flask_run_cmdline,
group_engines_in_tab,
)
from searx.webadapter import (
@@ -128,11 +130,6 @@ logger = logger.getChild('webapp')
warnings.simplefilter("always")
-# check secret_key
-if not searx_debug and settings['server']['secret_key'] == 'ultrasecretkey':
- logger.error('server.secret_key is not changed. Please use something else instead of ultrasecretkey.')
- sys.exit(1)
-
# about static
logger.debug('static directory is %s', settings['ui']['static_path'])
static_files = get_static_files(settings['ui']['static_path'])
@@ -1329,45 +1326,108 @@ def page_not_found(_e):
return render('404.html'), 404
-# see https://flask.palletsprojects.com/en/1.1.x/cli/
-# True if "FLASK_APP=searx/webapp.py FLASK_ENV=development flask run"
-flask_run_development = (
- os.environ.get("FLASK_APP") is not None and os.environ.get("FLASK_ENV") == 'development' and is_flask_run_cmdline()
-)
+def run():
+ """Runs the application on a local development server.
+
+ This run method is only called when SearXNG is started via ``__main__``::
+
+ python -m searx.webapp
+
+ Do not use :ref:`run() <flask.Flask.run>` in a production setting. It is
+ not intended to meet security and performance requirements for a production
+ server.
+
+ It is not recommended to use this function for development with automatic
+ reloading as this is badly supported. Instead you should be using the flask
+ command line script’s run support::
+
+ flask --app searx.webapp run --debug --reload --host 127.0.0.1 --port 8888
+
+ .. _Flask.run: https://flask.palletsprojects.com/en/stable/api/#flask.Flask.run
+ """
+
+ host: str = get_setting("server.bind_address") # type: ignore
+ port: int = get_setting("server.port") # type: ignore
+
+ if searx.sxng_debug:
+ logger.debug("run local development server (DEBUG) on %s:%s", host, port)
+ app.run(
+ debug=True,
+ port=port,
+ host=host,
+ threaded=True,
+ extra_files=[DEFAULT_SETTINGS_FILE],
+ )
+ else:
+ logger.debug("run local development server on %s:%s", host, port)
+ app.run(port=port, host=host, threaded=True)
+
+
+def is_werkzeug_reload_active() -> bool:
+ """Returns ``True`` if server is is launched by :ref:`werkzeug.serving` and
+ the ``use_reload`` argument was set to ``True``. If this is the case, it
+ should be avoided that the server is initialized twice (:py:obj:`init`,
+ :py:obj:`run`).
+
+ .. _werkzeug.serving:
+ https://werkzeug.palletsprojects.com/en/stable/serving/#werkzeug.serving.run_simple
+ """
+
+ # https://github.com/searxng/searxng/pull/1656#issuecomment-1214198941
+ # https://github.com/searxng/searxng/pull/1616#issuecomment-1206137468
-# True if reload feature is activated of werkzeug, False otherwise (including uwsgi, etc..)
-# __name__ != "__main__" if searx.webapp is imported (make test, make docs, uwsgi...)
-# see run() at the end of this file : searx_debug activates the reload feature.
-werkzeug_reloader = flask_run_development or (searx_debug and __name__ == "__main__")
+ frames = inspect.stack()
+
+ if len(frames) > 1 and frames[-2].filename.endswith('flask/cli.py'):
+ # server was launched by "flask run", is argument "--reload" set?
+ if "--reload" in sys.argv or "--debug" in sys.argv:
+ return True
+
+ elif frames[0].filename.endswith('searx/webapp.py'):
+ # server was launched by "python -m searx.webapp" / see run()
+ if searx.sxng_debug:
+ return True
+
+ return False
+
+
+def init():
+
+ if searx.sxng_debug or app.debug:
+ app.debug = True
+ searx.sxng_debug = True
+
+ # check secret_key in production
+
+ if not app.debug and get_setting("server.secret_key") == 'ultrasecretkey':
+ logger.error("server.secret_key is not changed. Please use something else instead of ultrasecretkey.")
+ sys.exit(1)
+
+ # When automatic reloading is activated stop Flask from initialising twice.
+ # - https://github.com/pallets/flask/issues/5307#issuecomment-1774646119
+ # - https://stackoverflow.com/a/25504196
+
+ reloader_active = is_werkzeug_reload_active()
+ werkzeug_run_main = is_running_from_reloader()
+
+ if reloader_active and not werkzeug_run_main:
+ logger.info("in reloading mode and not in main loop, cancel the initialization")
+ return
-# initialize the engines except on the first run of the werkzeug server.
-if not werkzeug_reloader or (werkzeug_reloader and os.environ.get("WERKZEUG_RUN_MAIN") == "true"):
locales_initialize()
redis_initialize()
searx.plugins.initialize(app)
- searx.search.initialize(
- enable_checker=True,
- check_network=True,
- enable_metrics=get_setting("general.enable_metrics"),
- )
- limiter.initialize(app, settings)
- favicons.init()
+ metrics: bool = get_setting("general.enable_metrics") # type: ignore
+ searx.search.initialize(enable_checker=True, check_network=True, enable_metrics=metrics)
-def run():
- logger.debug('starting webserver on %s:%s', settings['server']['bind_address'], settings['server']['port'])
- app.run(
- debug=searx_debug,
- use_debugger=searx_debug,
- port=settings['server']['port'],
- host=settings['server']['bind_address'],
- threaded=True,
- extra_files=[DEFAULT_SETTINGS_FILE],
- )
+ limiter.initialize(app, settings)
+ favicons.init()
application = app
patch_application(app)
+init()
if __name__ == "__main__":
run()