Поймать неправильно%-кодированные URL-адреса в Django, чтобы вернуть пользовательскую страницу "ошибка 400"

Иногда другие веб-сайты используют неправильно закодированные в процентах URL-адреса для ссылки на наш сайт с поддержкой Django. Disqus.com и Twitter.com имеют одну и ту же проблему, поэтому в нашем случае нет ничего особенного: http://disqus.com/%C3A4. В этом URL отсутствует второй%. Действительный URL выглядит следующим образом: http://disqus.com/%C3%A4

Django возвращает пустую страницу ошибки 400 (неверный запрос). Тем не менее, мы хотели бы уловить ошибку, и вместо того, чтобы возвращать простую неинформативную страницу, мы хотели бы показать нашим пользователям по крайней мере нашу пользовательскую страницу 404. Более того, мы хотели бы проверить входной URL-адрес на отсутствие%-символов или чего-либо подобного, чтобы проверить его формат. MiddleWare/process_request вызывается даже с нашими нынешними 400 ошибками, поэтому у нас есть ловушка для отлова ошибки.

Мы хотели бы решить эту проблему на нашем сайте. Есть ли лучшая практика...? А обработчик 400 был бы хорош - возможно ли создать его самостоятельно?

2 ответа

Решение

Как уже написано в виде комментария в ответе Кэти, это действительно хорошо, но не работает в данном конкретном случае, я публикую наше текущее, немного хакерское решение здесь в качестве другого ответа:

По-видимому, эта ошибка не может быть переопределена в MiddleWares Django. Это ошибка декодирования UNICODE, которая запускается внутри WSGIHandler в \django\core\handlers\wsgi.py. Чтобы быть точным, это

path_info = force_unicode(environ.get('PATH_INFO', u'/'))

внутри WSGIRequest, который вызывает проблему. Это в основном правильное поведение Django, но, как описано в моем вопросе, мы просто хотим показать нашим пользователям что-то более полезное, чем пустая страница с ошибками. Поэтому мы проверяем входящие запросы URL на действительные символы UNICODE, прежде чем передавать их нашему WSGIHandler. Этот пост в блоге указал нам правильное направление: http://codeinthehole.com/writing/django-nginx-wsgi-and-encoded-slashes/

Таким образом, мы перенаправляем недопустимые URL-адреса внутри нашего wsgi.py следующим образом:

os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'

import django.core.handlers.wsgi
_application = django.core.handlers.wsgi.WSGIHandler()

# for Django 1.7+
# from django.core.wsgi import get_wsgi_application
# _application = get_wsgi_application()

from django.utils.encoding import force_unicode
def application(environ, start_response):
    try:
        path_info = force_unicode(environ.get('PATH_INFO', u'/'))
    except:
        environ['PATH_INFO'] = u'/'
    return _application(environ, start_response)

Подклассы WSGHandler вместо этого также должны работать. В этом примере мы просто перенаправляем недопустимые URL-адреса в корень нашего сайта "/". Но вы также можете перенаправить на любой пользовательский URL-адрес страницы с ошибкой или попробовать санировать свой URL-адрес... У нас это работает, но, может быть, есть лучшее решение.

Создайте 404.html в своем шаблоне, затем поместите это в свой urls.py

#handle the errors    
from django.utils.functional import curry
from django.views.defaults import *

handler404 = curry(page_not_found, template_name='404.html')

You can also handle other errors like this:
handler500 = curry(server_error, template_name='500.html')
handler403 = curry(permission_denied, template_name='403.html')

Обрабатывает любые типы ошибок. Вы получите представление здесь.

https://github.com/Roejames12/django-error-pages
Другие вопросы по тегам