Repository: searx/searx

Issue:
Unable to access /config when running under Python 3, throws exception.
Hi.  I'm trying to run Searx under Python 3 (v3.7.2).

When I try to look at the Searx server configuration by GETting the /config rail with cURL, wget, or my web browser, the server throws an HTTP 500 error.  Searx throws the following exception on the console:

```
ERROR:flask.app:Exception on /config [GET]
Traceback (most recent call last):
  File "/Users/egrejda/searx/env/lib/python3.7/site-packages/flask/app.py", line 2292, in wsgi_app
    response = self.full_dispatch_request()
  File "/Users/egrejda/searx/env/lib/python3.7/site-packages/flask/app.py", line 1815, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/Users/egrejda/searx/env/lib/python3.7/site-packages/flask/app.py", line 1718, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/Users/egrejda/searx/env/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise
    raise value
  File "/Users/egrejda/searx/env/lib/python3.7/site-packages/flask/app.py", line 1813, in full_dispatch_request
    rv = self.dispatch_request()
  File "/Users/egrejda/searx/env/lib/python3.7/site-packages/flask/app.py", line 1799, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "searx/webapp.py", line 875, in config
    'default_doi_resolver': settings['default_doi_resolver'],
  File "/Users/egrejda/searx/env/lib/python3.7/site-packages/flask/json/__init__.py", line 321, in jsonify
    dumps(data, indent=indent, separators=separators) + '\n',
  File "/Users/egrejda/searx/env/lib/python3.7/site-packages/flask/json/__init__.py", line 179, in dumps
    rv = _json.dumps(obj, **kwargs)
  File "/usr/local/Cellar/python/3.7.2_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/__init__.py", line 238, in dumps
    **kw).encode(obj)
  File "/usr/local/Cellar/python/3.7.2_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/local/Cellar/python/3.7.2_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/Users/egrejda/searx/env/lib/python3.7/site-packages/flask/json/__init__.py", line 81, in default
    return _json.JSONEncoder.default(self, o)
  File "/usr/local/Cellar/python/3.7.2_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type dict_keys is not JSON serializable
INFO:werkzeug:127.0.0.1 - - [16/May/2019 11:10:45] "GET /config HTTP/1.1" 500 -
```

I can load the Searx frontpage normally in a browser under Python 3, and it works as expected.  Searx also seems to work just fine under Python 2; I routinely use it about a dozen times a day without trouble.  The /config rail and the API work just fine with Python 2, also.

Reproduced on: Mac OSX v1.13.6, Arch Linux, Ubuntu v18.04.


Discussion:

Resolving patch:
diff --git a/searx/webapp.py b/searx/webapp.py
--- a/searx/webapp.py
+++ b/searx/webapp.py
@@ -846,7 +846,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,
@@ -854,7 +854,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,


Test patch:
diff --git a/tests/unit/test_webapp.py b/tests/unit/test_webapp.py
--- a/tests/unit/test_webapp.py
+++ b/tests/unit/test_webapp.py
@@ -157,3 +157,9 @@ def test_opensearch_xml(self):
     def test_favicon(self):
         result = self.app.get('/favicon.ico')
         self.assertEqual(result.status_code, 200)
+
+    def test_config(self):
+        result = self.app.get('/config')
+        self.assertEqual(result.status_code, 200)
+        json_result = result.get_json()
+        self.assertTrue(json_result)