Кодирование ссылок — это та проблема, которая хорошо умеет скрываться. Её сложно заметить, до поры до времени вы о ней даже на задумываетесь. А потом случайно узнаёте о том, что сайт сломан. Сломан он вот уже как полгода. Часть его страниц просто не работают. Пускай вы даже всё тестировали и всё проверяли, но они сломались, внезапно и незаметно.
Подробнее о проблеме:
Самая большая проблема — это тестирование. Что не видно — то сложно чинить.
Если вы работает с шаблонами, то есть такой способ. Проделать его надо с каждой подстановкой адреса. Прямо в шаблоне подмените переменную {{ some_var }}
на строку с зашитым в неё адресом. Выглядеть будет примерно так:
{{ 'http://...some-url...' }}
Если не хотите трогать шаблон, то сделайте то же самое внутри Python скрипта перед отправкой данных в шаблон.
Теперь подмените символы в адресе на заведомо запрещённые. Если то была картинка photo.png
, то пусть станет фото с котиком.png
. Если GET параметр, то пусть тоже получит вымышленное значение с пробелами и кириллицой. Не важно существует такой адрес или нет, просто проверьте итоговую HTML разметку, на глаз или через W3C Validator.
В шаблоне не должно быть путей: <img src="{{ photo_path }}"/>
. Так тоже опасно: <img src="images/{{ photo }}"/>
. Не должно быть в шаблоне и GET параметров: <a href="./search?q={{ text }}"
. В обоих случаях необходимо кодирование. На стороне Python это делается с помощью urllib.parse.quote
и urllib.parse.urlencode
. В шаблонах Django и Jinja2 — с помощью шаблонного фильтра urlencode
.
Исключения из правил:
- Слаги (slug) — это фрагмент адреса с ограниченным набором символов. Всё, что разрешено в слаге можно использовать и в url. What is slug.
- Шаблонные теги
{% url ... %}
,{% static ... %}
в Django. Они сами беспокоятся о кодировании url.