diff options
Diffstat (limited to 'searx/webapp.py')
| -rw-r--r-- | searx/webapp.py | 110 |
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, |