diff --git a/app-config/nginx/nginx.conf b/app-config/nginx/nginx.conf
index 0895e583..8104caa3 100644
--- a/app-config/nginx/nginx.conf
+++ b/app-config/nginx/nginx.conf
@@ -66,10 +66,20 @@ http {
return 302 /auth/login;
}
+ location @proxy_404_error_handler {
+ # Pass the request on to the webservice. Most likely the URI won't
+ # exist so we get a 404 from that service instead (good as the 404
+ # pages are consistent).
+ proxy_pass http://cara-webservice:8080/$request_uri;
+ }
+
location /voila-server/ {
+ proxy_intercept_errors on;
+
# Anything under voila-server or expert-app is authenticated.
auth_request /auth/probe;
error_page 401 = @error401;
+ error_page 404 = @proxy_404_error_handler;
# cara-app is the name of the voila server in each of docker-compose,
# test-cara.web.cern.ch and cara.web.cern.ch.
diff --git a/app.sh b/app.sh
index d4fdf7c5..a9fc0e45 100755
--- a/app.sh
+++ b/app.sh
@@ -1,6 +1,6 @@
if [[ "$APP_NAME" == "cara-webservice" ]]; then
echo "Starting the cara webservice"
- python -m cara.apps.calculator
+ python -m cara.apps.calculator --no-debug
elif [[ "$APP_NAME" == "cara-voila" ]]; then
echo "Starting the voila service"
voila app/ --port=8080 --no-browser --base_url=/voila-server/ --Voila.tornado_settings="{'allow_origin': '*'}"
diff --git a/cara/apps/calculator/__init__.py b/cara/apps/calculator/__init__.py
index 96f8bd83..d22e8846 100644
--- a/cara/apps/calculator/__init__.py
+++ b/cara/apps/calculator/__init__.py
@@ -1,7 +1,10 @@
+import datetime
import html
import json
import os
from pathlib import Path
+import traceback
+import uuid
import jinja2
from tornado.web import Application, RequestHandler, StaticFileHandler
@@ -38,6 +41,39 @@ class BaseRequestHandler(RequestHandler):
else:
self.current_user = AnonymousUser()
+ def write_error(self, status_code: int, **kwargs) -> None:
+ template = self.settings["template_environment"].get_template(
+ "page.html.j2")
+
+ error_id = uuid.uuid4()
+ contents = (
+ f'Unfortunately an error occurred when processing your request. '
+ f'Please let us know about this issue with as much detail as possible at '
+ f'CARA-dev@cern.ch, reporting status '
+ f'code {status_code}, the error id of "{error_id}" and the time of the '
+ f'request ({datetime.datetime.utcnow()}).
'
+ )
+ # Print the error to the log (and not to the browser!)
+ if "exc_info" in kwargs:
+ print(f"ERROR UUID {error_id}")
+ print(traceback.format_exc())
+ self.finish(template.render(
+ user=self.current_user,
+ contents=contents
+ ))
+
+
+class Missing404Handler(BaseRequestHandler):
+ async def prepare(self):
+ await super().prepare()
+ self.set_status(404)
+ template = self.settings["template_environment"].get_template(
+ "page.html.j2")
+ self.finish(template.render(
+ user=self.current_user,
+ contents='Unfortunately the page you were looking for does not exist.
'
+ ))
+
class ConcentrationModel(BaseRequestHandler):
def post(self):
@@ -128,6 +164,7 @@ def make_app(debug=False, prefix='/calculator'):
urls,
debug=debug,
template_environment=template_environment,
+ default_handler_class=Missing404Handler,
xsrf_cookies=True,
# COOKIE_SECRET being undefined will result in no login information being
# presented to the user.