Кодирование ссылок — это та проблема, которая хорошо умеет скрываться. Её сложно заметить, до поры до времени вы о ней даже на задумываетесь. А потом случайно узнаёте о том, что сайт сломан. Сломан он вот уже как полгода. Часть его страниц просто не работают. Пускай вы даже всё тестировали и всё проверяли, но они сломались, внезапно и незаметно.
Подробнее о проблеме:
Самая большая проблема — это тестирование. Что не видно — то сложно чинить.
Если вы работает с шаблонами, то есть такой способ. Проделать его надо с каждой подстановкой адреса. Прямо в шаблоне подмените переменную {{ 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.