Skip to content

Instantly share code, notes, and snippets.

@espretto
Last active August 29, 2015 14:03
Show Gist options
  • Save espretto/e2e4fc99555ba7fabc40 to your computer and use it in GitHub Desktop.
Save espretto/e2e4fc99555ba7fabc40 to your computer and use it in GitHub Desktop.
python: cors headers
# 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
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