From ce6b3192880cd66a0a16c3d88e0da969f6ce6e42 Mon Sep 17 00:00:00 2001 From: David Baumgold Date: Thu, 20 Jun 2013 16:45:46 -0400 Subject: [PATCH 1/5] Added jsonable_server_error in common/util/views.py --- common/djangoapps/util/views.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/common/djangoapps/util/views.py b/common/djangoapps/util/views.py index 851202caec..10492e383d 100644 --- a/common/djangoapps/util/views.py +++ b/common/djangoapps/util/views.py @@ -4,7 +4,10 @@ import sys from django.conf import settings from django.core.validators import ValidationError, validate_email -from django.http import Http404, HttpResponse, HttpResponseNotAllowed +from django.views.decorators.csrf import requires_csrf_token +from django.views.defaults import server_error +from django.http import (Http404, HttpResponse, HttpResponseNotAllowed, + HttpResponseServerError) from dogapi import dog_stats_api from mitxmako.shortcuts import render_to_response import zendesk @@ -16,6 +19,19 @@ import track.views log = logging.getLogger(__name__) +@requires_csrf_token +def jsonable_server_error(request, template_name='500.html'): + """ + 500 error handler that serves JSON on an AJAX request, and proxies + to the Django default `server_error` view otherwise. + """ + if request.is_ajax(): + msg = {"error": "The edX servers encountered an error"} + return HttpResponseServerError(json.dumps(msg)) + else: + return server_error(request, template_name=template_name) + + def calculate(request): ''' Calculator in footer of every page. ''' equation = request.GET['equation'] @@ -228,4 +244,3 @@ def accepts(request, media_type): """Return whether this request has an Accept header that matches type""" accept = parse_accept_header(request.META.get("HTTP_ACCEPT", "")) return media_type in [t for (t, p, q) in accept] - From 923bcc555c6a039df649d1c2725cc67ad8c79660 Mon Sep 17 00:00:00 2001 From: David Baumgold Date: Thu, 20 Jun 2013 17:18:56 -0400 Subject: [PATCH 2/5] Make CMS errors JSON-able if requested via AJAX --- cms/djangoapps/contentstore/views/error.py | 27 +++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/cms/djangoapps/contentstore/views/error.py b/cms/djangoapps/contentstore/views/error.py index 0292b9d389..5a34af36bc 100644 --- a/cms/djangoapps/contentstore/views/error.py +++ b/cms/djangoapps/contentstore/views/error.py @@ -1,20 +1,45 @@ -from django.http import HttpResponseServerError, HttpResponseNotFound +from django.http import (HttpResponse, HttpResponseServerError, + HttpResponseNotFound) from mitxmako.shortcuts import render_to_string, render_to_response +import functools +import json __all__ = ['not_found', 'server_error', 'render_404', 'render_500'] +def jsonable_error(status=500, message="The Studio servers encountered an error"): + """ + A decorator to make an error view return an JSON-formatted message if + it was requested via AJAX. + """ + def outer(func): + @functools.wraps(func) + def inner(request, *args, **kwargs): + if request.is_ajax(): + content = json.dumps({"error": message}) + return HttpResponse(content, content_type="application/json", + status=status) + else: + return func(request, *args, **kwargs) + return inner + return outer + + +@jsonable_error(404, "Resource not found") def not_found(request): return render_to_response('error.html', {'error': '404'}) +@jsonable_error(500, "The Studio servers encountered an error") def server_error(request): return render_to_response('error.html', {'error': '500'}) +@jsonable_error(404, "Resource not found") def render_404(request): return HttpResponseNotFound(render_to_string('404.html', {})) +@jsonable_error(500, "The Studio servers encountered an error") def render_500(request): return HttpResponseServerError(render_to_string('500.html', {})) From 8bfcbb6675ecf04d672c674870d7e802245101b3 Mon Sep 17 00:00:00 2001 From: David Baumgold Date: Thu, 20 Jun 2013 17:20:33 -0400 Subject: [PATCH 3/5] Make notifyOnError handler try to parse response as JSON --- cms/static/coffee/src/main.coffee | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cms/static/coffee/src/main.coffee b/cms/static/coffee/src/main.coffee index 8043b41638..ae64e90375 100644 --- a/cms/static/coffee/src/main.coffee +++ b/cms/static/coffee/src/main.coffee @@ -19,7 +19,10 @@ $ -> if ajaxSettings.notifyOnError is false return if jqXHR.responseText - message = _.str.truncate(jqXHR.responseText, 300) + try + message = JSON.parse(jqXHR.responseText).error + catch + message = _.str.truncate(jqXHR.responseText, 300) else message = gettext("This may be happening because of an error with our server or your internet connection. Try refreshing the page or making sure you are online.") msg = new CMS.Views.Notification.Error( From 1fee805c9a5ab7cd55886aafd7356a282e965797 Mon Sep 17 00:00:00 2001 From: David Baumgold Date: Wed, 26 Jun 2013 11:35:27 -0400 Subject: [PATCH 4/5] Adjust indentation to make coffeescript happy --- cms/static/coffee/src/main.coffee | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cms/static/coffee/src/main.coffee b/cms/static/coffee/src/main.coffee index ae64e90375..a6e9d43daa 100644 --- a/cms/static/coffee/src/main.coffee +++ b/cms/static/coffee/src/main.coffee @@ -19,15 +19,15 @@ $ -> if ajaxSettings.notifyOnError is false return if jqXHR.responseText - try - message = JSON.parse(jqXHR.responseText).error - catch - message = _.str.truncate(jqXHR.responseText, 300) + try + message = JSON.parse(jqXHR.responseText).error + catch + message = _.str.truncate(jqXHR.responseText, 300) else - message = gettext("This may be happening because of an error with our server or your internet connection. Try refreshing the page or making sure you are online.") + message = gettext("This may be happening because of an error with our server or your internet connection. Try refreshing the page or making sure you are online.") msg = new CMS.Views.Notification.Error( - "title": gettext("Studio's having trouble saving your work") - "message": message + "title": gettext("Studio's having trouble saving your work") + "message": message ) msg.show() From 7824b8c8f22d5e679cb902ac8860a2c8f06c1bbe Mon Sep 17 00:00:00 2001 From: David Baumgold Date: Wed, 26 Jun 2013 16:24:53 -0400 Subject: [PATCH 5/5] Fix coffeescript issue on Linux On Linux, coffeescript refuses to compile unless the `catch` keyword has an error variable to bind to. On Mac, it works just fine either way. Go figure. --- cms/static/coffee/src/main.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cms/static/coffee/src/main.coffee b/cms/static/coffee/src/main.coffee index a6e9d43daa..863d21d846 100644 --- a/cms/static/coffee/src/main.coffee +++ b/cms/static/coffee/src/main.coffee @@ -21,7 +21,7 @@ $ -> if jqXHR.responseText try message = JSON.parse(jqXHR.responseText).error - catch + catch error message = _.str.truncate(jqXHR.responseText, 300) else message = gettext("This may be happening because of an error with our server or your internet connection. Try refreshing the page or making sure you are online.")