|
@@ -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()
|