Last active
August 29, 2015 14:03
-
-
Save espretto/e2e4fc99555ba7fabc40 to your computer and use it in GitHub Desktop.
python: cors headers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# decorators | |
from functools import wraps | |
from django.http import HttpRequest | |
ALLOWED_HEADERS = ( | |
'content-type', | |
'accept', | |
'origin', | |
'authorization', | |
'x-requested-with', | |
'x-csrftoken', | |
) | |
def corsify(headers={}): | |
""" | |
returns a decorator - remember parenthesis - that adds CORS response headers | |
allows for the requested method, any origin and | |
the intersection of the requested and allowed headers by default | |
you may override the defaults and/or | |
add any other HTTP headers as follows | |
`` | |
@corsify({ | |
'Access-Control-Allow-Origin' : ','.join(('your', 'white-listed', 'domains')), | |
'Content-Type' : 'application/json' | |
}) | |
""" | |
def wrap(view_function): | |
def wrapped_view_function(request, *args, **kwargs): | |
response = view_function(request, *args, **kwargs) | |
# early` exit | |
if response is None: | |
return | |
# work around class method decoration | |
if not isinstance(request, HttpRequest): | |
request = args[0] | |
headers.setdefault('Access-Control-Allow-Origin', '*') | |
if not 'Access-Control-Allow-Headers' in headers: | |
requested_headers = request.META.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS') | |
if requested_headers is not None: | |
# use set comprehension to avoid duplicates | |
# split by whitespace sequences | |
intersection = {header for header in requested_headers\ | |
.lower()\ | |
.replace(',', ' ')\ | |
.split() if header in ALLOWED_HEADERS | |
} | |
response['Access-Control-Allow-Headers'] = ','.join( intersection ) | |
if not 'Access-Control-Allow-Methods' in headers: | |
requested_method = request.META.get('HTTP_ACCESS_CONTROL_REQUEST_METHOD') | |
if requested_method is not None: | |
response['Access-Control-Allow-Methods'] = requested_method | |
# set the headers | |
for header, value in headers.items(): | |
response[header] = value | |
return response | |
# preserve view_function's docstring, __name__ attribute etc. for pydoc | |
return wraps(view_function)(wrapped_view_function) | |
return wrap |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from django.conf import settings | |
from django.http import HttpResponse | |
from .corsify import corsify | |
class XHeaderCookieMiddleware(object): | |
""" | |
set X-Headers as Cookies where appropriate | |
""" | |
def process_request(self, request): | |
csrf_token = request.META.get('HTTP_X_CSRFTOKEN') | |
if csrf_token is not None: | |
request.COOKIES[settings.CSRF_COOKIE_NAME] = csrf_token | |
class PreflightMiddleware(object): | |
""" | |
prefetch HTTP request with verb "OPTIONS" | |
""" | |
@corsify({'Access-Control-Max-Age': '86400'}) | |
def process_request(self, request): | |
if request.method == 'OPTIONS': | |
return HttpResponse() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment