Рубрики
Без рубрики

Почему URL -адреса жестко: параметры пути и Urlparse

Как я обнаружил почти совершенно неиспользованную функцию URL из таинственного API в функции Python urlparse. Tagged с Python, сегодня, URL.

Это Кросс-пост из моего блога Python ♥ http Анкет Если вам понравится мой контент и хотите его раньше, вы можете Следуй за мной через RSS Анкет

Добро пожаловать в первую часть «Почему URL -адреса жестко»: серию историй, которые я накопил, прочитав многое о URL.

Мы принимаем URL -адреса как должное и в основном думаем о них как о очень простых вещах из -за того, как часто мы взаимодействуем с чистыми и простыми URL -адресами, такими как https://example.com Анкет Мало ли вы знаете, что существуют десятилетия древней темной магии, которые произошли, прежде чем мы закончили с URL -адресами, которые мы знаем и любим сегодня.

Эта история о поиске таинственного API в Python’s urlparse Функция и обнаружение теперь почти полностью неиспользованную функцию URL. Пойдем со мной!:)

Сравнение Urlparse с RFC 3986

Я оценивал urlparse из urllib.parse модуль и то, как он выполнялся по сравнению с другими библиотеками анализатора URL.

В рамках документации упоминается, что URL -адреса проанализированы в соответствии с RFC 3986 который представляет собой набор правил, которые описывают, как сегментировать URL на разные компоненты. Давайте быстро рассмотрим этот стандарт, чтобы увидеть, какие части URL мы видим.

Есть милая маленькая диаграмма ASCII, демонстрирующая все части URL:

 foo://example.com:8042/over/there?name=ferret#nose
 \_/   \______________/\_________/ \_________/ \__/
  |           |            |            |        |
scheme     authority       path        query   fragment

… а затем авторитет Секция дополнительно разложится на:

authority = [ userinfo "@" ] host [ ":" port ]

Одна из лучших частей чтения RFCs думает о том, сколько усилий люди прикладывают в восхитительное искусство ASCII:)

Хорошо, теперь, когда мы знаем, чего ожидать, давайте попробуем urlparse с URL -адресом от RFC:

>>> from urllib.parse import urlparse
>>> url = (
... "foo://user:pass@example.com:8042"
... "/over/there?name=ferret#nose"
)
>>> parts = urlparse(url)
>>> parts
ParseResult(
    scheme='foo',
    netloc='user:pass@example.com:8042',
    path='/over/there',
    params='',
    query='name=ferret',
    fragment='nose'
)
>>> parts.hostname
'example.com'
>>> parts.port
8042
>>> parts.username
'user'
>>> parts.password
'pass'

Хорошо, похоже, что у нас это как картирование с Parseresult до RFC 3986:

  • parts.scheme -> схема
  • parts.netloc -> орган власти

    • parts.username : пароль -> userInfo
    • части.hostname -> хозяин
    • parts.port -> порт
  • части.path -> дорожка
  • части.params -> ???
  • части.query -> запрос
  • части.fragment -> фрагмент

Заметьте ??? в списке? Я тоже был в замешательстве. Независимо от того, что я вложил в свой URL, я не мог получить ничего, чтобы появиться в Parseresult.params Анкет

Документация для Parseresult.params «параметры для последнего элемента пути», а затем не упоминается нигде. Гуглинг тоже жесткий, потому что « Params » – это запросы, способ добавить к строке запроса для запрошенного URL, поэтому большинство результатов об этом.

При поиске «параметров пути» я нашел Эта статья 2008 года который указал на последний абзац RFC 3986 Раздел 3.3 что объясняет параметры пути:

Aside from dot-segments in hierarchical paths,
a path segment is considered opaque by the
generic syntax.  URI producing applications
often use the reserved characters allowed in a
segment to delimit scheme-specific or dereference-
handler-specific subcomponents.  For example,
the semicolon (";") and equals ("=") reserved
characters are often used to delimit parameters
and parameter values applicable to that segment.

Так ; и = иметь особое значение в рамках Путь , давайте бросим их в urlparse и посмотрим, что произойдет:

>>> urlparse("http://example.com/a;z=y;x/b;c;d=e")
ParseResult(
    scheme='http',
    netloc='example.com',
    path='/a;z=y;x/b',
    params='c;d=e',
    query='',
    fragment=''
)

Да, я не ожидал, что это вытащит значения на самом деле за пределами Путь составная часть. И похоже, что он только вытащил параметры из последнего сегмента, /a; z = y; x/ нетронут. Интересно, сколько ошибок скрывается из -за этой причуды.:)

Так что, если вы полагаетесь на анализ URL и напрямую осматривать Путь Компонент Убедитесь, что вы проверяете свою реализацию и измените ее, чтобы добавить f "; {result.params}" Если Params это непусты. Либо это, либо используйте анализатор URL, который не имеет этой причуды, как RFC3986

Я особенно рекомендую использовать другую библиотеку, если вы принимаете решения о безопасности на основе URL. Запись с 2011 года Подробнее о проблеме безопасности, связанной с параметрами пути какое приложение с использованием Parseresult.path Один, вероятно, также будет уязвим.

Надеюсь, вы что -то узнали и останетесь в безопасности!

Оригинал: “https://dev.to/sethmlarson/why-urls-are-hard-path-parameters-and-urlparse-c2n”