summaryrefslogtreecommitdiff
path: root/searx/webapp.py
diff options
context:
space:
mode:
Diffstat (limited to 'searx/webapp.py')
-rw-r--r--searx/webapp.py110
1 files changed, 80 insertions, 30 deletions
diff --git a/searx/webapp.py b/searx/webapp.py
index 7145caca9..7cf4106d3 100644
--- a/searx/webapp.py
+++ b/searx/webapp.py
@@ -41,8 +41,12 @@ except:
logger.critical("cannot import dependency: pygments")
from sys import exit
exit(1)
-from cgi import escape
+try:
+ from cgi import escape
+except:
+ from html import escape
from datetime import datetime, timedelta
+from time import time
from werkzeug.contrib.fixers import ProxyFix
from flask import (
Flask, request, render_template, url_for, Response, make_response,
@@ -123,6 +127,7 @@ app = Flask(
app.jinja_env.trim_blocks = True
app.jinja_env.lstrip_blocks = True
+app.jinja_env.add_extension('jinja2.ext.loopcontrols')
app.secret_key = settings['server']['secret_key']
if not searx_debug \
@@ -152,23 +157,18 @@ outgoing_proxies = settings['outgoing'].get('proxies') or None
@babel.localeselector
def get_locale():
- locale = request.accept_languages.best_match(settings['locales'].keys())
-
- if request.preferences.get_value('locale') != '':
- locale = request.preferences.get_value('locale')
+ if 'locale' in request.form\
+ and request.form['locale'] in settings['locales']:
+ return request.form['locale']
if 'locale' in request.args\
and request.args['locale'] in settings['locales']:
- locale = request.args['locale']
-
- if 'locale' in request.form\
- and request.form['locale'] in settings['locales']:
- locale = request.form['locale']
+ return request.args['locale']
- if locale == 'zh_TW':
- locale = 'zh_Hant_TW'
+ if request.preferences.get_value('locale') != '':
+ return request.preferences.get_value('locale')
- return locale
+ return request.accept_languages.best_match(settings['locales'].keys())
# code-highlighter
@@ -295,6 +295,9 @@ def image_proxify(url):
if not request.preferences.get_value('image_proxy'):
return url
+ if url.startswith('data:image/jpeg;base64,'):
+ return url
+
if settings.get('result_proxy'):
return proxify(url)
@@ -399,6 +402,8 @@ def render(template_name, override_theme=None, **kwargs):
@app.before_request
def pre_request():
+ request.start_time = time()
+ request.timings = []
request.errors = []
preferences = Preferences(themes, list(categories.keys()), engines, plugins)
@@ -434,6 +439,21 @@ def pre_request():
request.user_plugins.append(plugin)
+@app.after_request
+def post_request(response):
+ total_time = time() - request.start_time
+ timings_all = ['total;dur=' + str(round(total_time * 1000, 3))]
+ if len(request.timings) > 0:
+ timings = sorted(request.timings, key=lambda v: v['total'])
+ timings_total = ['total_' + str(i) + '_' + v['engine'] +
+ ';dur=' + str(round(v['total'] * 1000, 3)) for i, v in enumerate(timings)]
+ timings_load = ['load_' + str(i) + '_' + v['engine'] +
+ ';dur=' + str(round(v['load'] * 1000, 3)) for i, v in enumerate(timings)]
+ timings_all = timings_all + timings_total + timings_load
+ response.headers.add('Server-Timing', ', '.join(timings_all))
+ return response
+
+
def index_error(output_format, error_message):
if output_format == 'json':
return Response(json.dumps({'error': error_message}),
@@ -486,9 +506,10 @@ def index():
# search
search_query = None
+ raw_text_query = None
result_container = None
try:
- search_query = get_search_query_from_webapp(request.preferences, request.form)
+ search_query, raw_text_query = get_search_query_from_webapp(request.preferences, request.form)
# search = Search(search_query) # without plugins
search = SearchWithPlugins(search_query, request.user_plugins, request)
result_container = search.search()
@@ -511,19 +532,24 @@ def index():
# UI
advanced_search = request.form.get('advanced_search', None)
+ # Server-Timing header
+ request.timings = result_container.get_timings()
+
# output
for result in results:
if output_format == 'html':
if 'content' in result and result['content']:
result['content'] = highlight_content(escape(result['content'][:1024]), search_query.query)
- result['title'] = highlight_content(escape(result['title'] or u''), search_query.query)
+ if 'title' in result and result['title']:
+ result['title'] = highlight_content(escape(result['title'] or u''), search_query.query)
else:
if result.get('content'):
result['content'] = html_to_text(result['content']).strip()
# removing html content and whitespace duplications
result['title'] = ' '.join(html_to_text(result['title']).strip().split())
- result['pretty_url'] = prettify_url(result['url'])
+ if 'url' in result:
+ result['pretty_url'] = prettify_url(result['url'])
# TODO, check if timezone is calculated right
if 'publishedDate' in result:
@@ -577,6 +603,21 @@ def index():
)
return Response(response_rss, mimetype='text/xml')
+ # HTML output format
+
+ # suggestions: use RawTextQuery to get the suggestion URLs with the same bang
+ suggestion_urls = map(lambda suggestion: {
+ 'url': raw_text_query.changeSearchQuery(suggestion).getFullQuery(),
+ 'title': suggestion
+ },
+ result_container.suggestions)
+
+ correction_urls = list(map(lambda correction: {
+ 'url': raw_text_query.changeSearchQuery(correction).getFullQuery(),
+ 'title': correction
+ },
+ result_container.corrections))
+ #
return render(
'results.html',
results=results,
@@ -586,9 +627,9 @@ def index():
time_range=search_query.time_range,
number_of_results=format_decimal(number_of_results),
advanced_search=advanced_search,
- suggestions=result_container.suggestions,
+ suggestions=suggestion_urls,
answers=result_container.answers,
- corrections=result_container.corrections,
+ corrections=correction_urls,
infoboxes=result_container.infoboxes,
paging=result_container.paging,
unresponsive_engines=result_container.unresponsive_engines,
@@ -597,7 +638,8 @@ def index():
fallback=settings['search']['language']),
base_url=get_base_url(),
theme=get_current_theme_name(),
- favicons=global_favicons[themes.index(get_current_theme_name())]
+ favicons=global_favicons[themes.index(get_current_theme_name())],
+ timeout_limit=request.form.get('timeout_limit', None)
)
@@ -633,12 +675,15 @@ def autocompleter():
# parse searx specific autocompleter results like !bang
raw_results = searx_bang(raw_text_query)
- # normal autocompletion results only appear if max 3 inner results returned
- if len(raw_results) <= 3 and completer:
+ # normal autocompletion results only appear if no inner results returned
+ # and there is a query part besides the engine and language bangs
+ if len(raw_results) == 0 and completer and (len(raw_text_query.query_parts) > 1 or
+ (len(raw_text_query.languages) == 0 and
+ not raw_text_query.specific)):
# get language from cookie
language = request.preferences.get_value('language')
- if not language:
- language = settings['search']['language']
+ if not language or language == 'all':
+ language = 'en'
else:
language = language.split('-')[0]
# run autocompletion
@@ -691,10 +736,7 @@ def preferences():
'warn_time': False}
if e.timeout > settings['outgoing']['request_timeout']:
stats[e.name]['warn_timeout'] = True
- if match_language(request.preferences.get_value('language'),
- getattr(e, 'supported_languages', []),
- getattr(e, 'language_aliases', {}), None):
- stats[e.name]['supports_selected_language'] = True
+ stats[e.name]['supports_selected_language'] = _is_selected_language_supported(e, request.preferences)
# get first element [0], the engine time,
# and then the second element [1] : the time (the first one is the label)
@@ -725,6 +767,14 @@ def preferences():
preferences=True)
+def _is_selected_language_supported(engine, preferences):
+ language = preferences.get_value('language')
+ return (language == 'all'
+ or match_language(language,
+ getattr(engine, 'supported_languages', []),
+ getattr(engine, 'language_aliases', {}), None))
+
+
@app.route('/image_proxy', methods=['GET'])
def image_proxy():
url = request.args.get('url').encode('utf-8')
@@ -838,7 +888,7 @@ def clear_cookies():
@app.route('/config')
def config():
- return jsonify({'categories': categories.keys(),
+ return jsonify({'categories': list(categories.keys()),
'engines': [{'name': engine_name,
'categories': engine.categories,
'shortcut': engine.shortcut,
@@ -846,7 +896,7 @@ def config():
'paging': engine.paging,
'language_support': engine.language_support,
'supported_languages':
- engine.supported_languages.keys()
+ list(engine.supported_languages.keys())
if isinstance(engine.supported_languages, dict)
else engine.supported_languages,
'safesearch': engine.safesearch,
@@ -874,7 +924,7 @@ def page_not_found(e):
def run():
- logger.debug('starting webserver on %s:%s', settings['server']['port'], settings['server']['bind_address'])
+ logger.debug('starting webserver on %s:%s', settings['server']['bind_address'], settings['server']['port'])
app.run(
debug=searx_debug,
use_debugger=searx_debug,