diff --git a/install_files/ansible-base/roles/app/templates/sites-available/journalist.conf b/install_files/ansible-base/roles/app/templates/sites-available/journalist.conf
index 4fd947c3e0..3beeec1418 100644
--- a/install_files/ansible-base/roles/app/templates/sites-available/journalist.conf
+++ b/install_files/ansible-base/roles/app/templates/sites-available/journalist.conf
@@ -31,18 +31,10 @@ Header set X-Content-Type-Options: nosniff
Header set X-Download-Options: noopen
Header set X-Content-Security-Policy: "default-src 'self'"
Header set Content-Security-Policy: "default-src 'self'"
-Header unset Etag
# Limit the max submitted size of requests.
LimitRequestBody 524288000
-#Redirect error pages to ensure headers are sent
-ErrorDocument 400 /notfound
-ErrorDocument 401 /notfound
-ErrorDocument 403 /notfound
-ErrorDocument 404 /notfound
-ErrorDocument 500 /error
-
Options None
AllowOverride None
@@ -53,11 +45,11 @@ ErrorDocument 500 /error
Options {{ apache_dir_options | default('None') }}
AllowOverride None
-
+
Order allow,deny
allow from {{ securedrop_app_apache_allow_from }}
-
+
Order deny,allow
Deny from all
@@ -66,11 +58,11 @@ ErrorDocument 500 /error
Options {{ apache_dir_options | default('None') }}
AllowOverride None
-
+
Order allow,deny
allow from {{ securedrop_app_apache_allow_from }}
-
+
Order deny,allow
Deny from all
diff --git a/molecule/testinfra/staging/app/apache/test_apache_journalist_interface.py b/molecule/testinfra/staging/app/apache/test_apache_journalist_interface.py
index 8c4609fedf..cc1a5341a8 100644
--- a/molecule/testinfra/staging/app/apache/test_apache_journalist_interface.py
+++ b/molecule/testinfra/staging/app/apache/test_apache_journalist_interface.py
@@ -16,7 +16,6 @@
"Header set X-Content-Security-Policy: \"default-src 'self'\"",
"Header set Content-Security-Policy: \"default-src 'self'\"",
'Header set Referrer-Policy "no-referrer"',
- 'Header unset Etag',
]
@@ -51,11 +50,11 @@ def test_apache_headers_journalist_interface(host, header):
Options None
AllowOverride None
-
+
Order allow,deny
allow from {apache_allow_from}
-
+
Order deny,allow
Deny from all
@@ -64,11 +63,11 @@ def test_apache_headers_journalist_interface(host, header):
Options None
AllowOverride None
-
+
Order allow,deny
allow from {apache_allow_from}
-
+
Order deny,allow
Deny from all
diff --git a/securedrop/journalist_app/api.py b/securedrop/journalist_app/api.py
index 01230b9d1b..0d2de87604 100644
--- a/securedrop/journalist_app/api.py
+++ b/securedrop/journalist_app/api.py
@@ -309,7 +309,7 @@ def get_current_user():
user = get_user_object(request)
return jsonify(user.to_json()), 200
- def _handle_http_exception(error):
+ def _handle_api_http_exception(error):
# Workaround for no blueprint-level 404/5 error handlers, see:
# https://github.com/pallets/flask/issues/503#issuecomment-71383286
response = jsonify({'error': error.name,
@@ -318,6 +318,6 @@ def _handle_http_exception(error):
return response, error.code
for code in default_exceptions:
- api.errorhandler(code)(_handle_http_exception)
+ api.errorhandler(code)(_handle_api_http_exception)
return api
diff --git a/securedrop/tests/test_journalist.py b/securedrop/tests/test_journalist.py
index 8100a0b748..dd81df6e95 100644
--- a/securedrop/tests/test_journalist.py
+++ b/securedrop/tests/test_journalist.py
@@ -2024,3 +2024,9 @@ def test_does_set_cookie_headers(journalist_app, test_journo):
observed_headers = response.headers
assert 'Set-Cookie' in observed_headers.keys()
assert 'Cookie' in observed_headers['Vary']
+
+
+def test_app_error_handlers_defined(journalist_app):
+ for status_code in [400, 401, 403, 404, 500]:
+ # This will raise KeyError if an app-wide error handler is not defined
+ assert journalist_app.error_handler_spec[None][status_code]
diff --git a/securedrop/tests/test_journalist_api.py b/securedrop/tests/test_journalist_api.py
index fc51e3982e..f99a277ea2 100644
--- a/securedrop/tests/test_journalist_api.py
+++ b/securedrop/tests/test_journalist_api.py
@@ -244,7 +244,16 @@ def test_user_without_token_cannot_post_protected_endpoints(journalist_app,
assert response.status_code == 403
-def test_api_404(journalist_app, journalist_api_token):
+def test_api_error_handlers_defined(journalist_app):
+ """Ensure the expected error handler is defined in the API blueprint"""
+ for status_code in [400, 401, 403, 404, 500]:
+ result = journalist_app.error_handler_spec['api'][status_code]
+
+ expected_error_handler = '_handle_api_http_exception'
+ assert result.values()[0].__name__ == expected_error_handler
+
+
+def test_api_error_handler_404(journalist_app, journalist_api_token):
with journalist_app.test_client() as app:
response = app.get('/api/v1/invalidendpoint',
headers=get_api_headers(journalist_api_token))