From 9bb4f1b992f026317558c0885edb97fc9c4213dc Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Tue, 10 Nov 2015 10:23:01 +0100 Subject: [PATCH] improve AJAX/JSONP support in decorators.json --- src/authentic2/decorators.py | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/src/authentic2/decorators.py b/src/authentic2/decorators.py index 01eaec8..bc20f66 100644 --- a/src/authentic2/decorators.py +++ b/src/authentic2/decorators.py @@ -258,26 +258,38 @@ def json(func): from . import cors @wraps(func) def f(request, *args, **kwargs): + jsonp = False + # Differentiate JSONP from AJAX + if request.method == 'GET': + for variable in ('jsonpCallback', 'callback'): + if variable in request.GET: + identifier = request.GET[variable] + if not re.match(r'^[$a-zA-Z_][0-9a-zA-Z_$]*$', identifier): + return HttpResponseBadRequest('invalid JSONP callback name') + jsonp = True + break # 1. check origin - origin = request.META.get('HTTP_ORIGIN') - if origin is None: + if jsonp: origin = request.META.get('HTTP_REFERER') + if not origin: + # JSONP is unusable for people without referers + return HttpResponseForbidden('bad origin') + origin = cors.make_origin(origin) + if not cors.check_origin(request, origin): + return HttpResponseForbidden('bad origin') + else: + origin = request.META.get('HTTP_ORIGIN') if origin: - origin = cors.make_origin(origin) - if not cors.check_origin(request, origin): - return HttpResponseForbidden('bad origin') + if not cors.check_origin(request, origin): + return HttpResponseForbidden('bad origin') # 2. build response result = func(request, *args, **kwargs) json_str = json_dumps(result) - response = HttpResponse(content_type='application/json') - for variable in ('jsonpCallback', 'callback'): - if variable in request.GET: - identifier = request.GET[variable] - if not re.match(r'^[$a-zA-Z_][0-9a-zA-Z_$]*$', identifier): - return HttpResponseBadRequest('invalid JSONP callback name') - json_str = '%s(%s);' % (identifier, json_str) - break + if jsonp: + response = HttpResponse(content_type='application/javascript') + json_str = '%s(%s);' % (identifier, json_str) else: + response = HttpResponse(content_type='application/json') response['Access-Control-Allow-Origin'] = origin response['Access-Control-Allow-Credentials'] = 'true' response['Access-Control-Allow-Headers'] = 'x-requested-with' -- 2.1.4