python - How do I handle utf-8 vs. punycode issues in Django's csrf middleware? -


i have domain non-ascii characters similar http://blå.no domain registered punycode equivalent:

xn--bl-zia.no 

which set in apache vhost:

<virtualhost *:443>     servername xn--bl-zia.no     ... 

the problem i'm seeing coming request containing:

'http_user_agent': 'mozilla/5.0 (windows nt 6.3; wow64; trident/7.0; rv:11.0) gecko', 'http_host': 'xn--bl-zia.no', 'server_name': 'xn--bl-zia.no', 'http_referer': 'https://bl\xc3\xa5.no/login/ka/?next=/start-exam/participant-login/', 'http_x_requested_with': 'xmlhttprequest', 

ie. referer sent utf-8 , not punycode. exception i'm getting is:

traceback (most recent call last):    file "/srv/cleanup-project/venv/dev/lib/python2.7/site-packages/django/core/handlers/base.py", line 153, in get_response     response = callback(request, **param_dict)    file "/srv/cleanup-project/venv/dev/lib/python2.7/site-packages/django/utils/decorators.py", line 87, in _wrapped_view     result = middleware.process_view(request, view_func, args, kwargs)    file "/srv/cleanup-project/venv/dev/lib/python2.7/site-packages/django/middleware/csrf.py", line 157, in process_view     reason = reason_bad_referer % (referer, good_referer)  unicodedecodeerror: 'ascii' codec can't decode byte 0xc3 in position 10: ordinal not in range(128) 

the relevant code in csrf.py is:

            good_referer = 'https://%s/' % request.get_host()             if not same_origin(referer, good_referer):                 reason = reason_bad_referer % (referer, good_referer) 

(get_host() uses server_name request)

is there native django way handle this, or need write middleware converts utf-8 punycode in domain part of referer header?

here's middleware solution..

import urlparse   class punycodeu8refererfixermiddleware(object):     def process_request(self, request):         servername = request.meta['server_name']         if 'xn--' not in servername:             return none          referer = request.meta.get("http_referer")         if not referer:             return none          url = urlparse.urlparse(referer)         try:             netloc = url.netloc.decode('u8')         except unicodedecodeerror:             return none          def isascii(txt):             return all(ord(ch) < 128 ch in txt)          netloc = '.'.join([             str(p) if isascii(p) else 'xn--' + p.encode('punycode')             p in netloc.split('.')         ])         url = url._replace(netloc=netloc)         request.meta['http_referer'] = urlparse.urlunparse(url)         return none 

it tries bail possible when detects can't useful. must installed before csrf middleware of course.


Comments

Popular posts from this blog

java - Spring Data JPA: Why findOne(id) executing delete query internally? -

python - Mongodb How to add addtional information when aggregating? -

java - Incorrect order of records in M-M relationship in hibernate -