Чем urllib.request отличается от curl или httpx по поведению? Получение 401 в запросе к Реестру контейнеров Google
В настоящее время я работаю над кодом для взаимодействия с изображениями в реестре контейнеров Google. У меня есть рабочий код, использующий простойcurl
а также httpx
. Я пытаюсь создать пакет без сторонних зависимостей. Меня интересует конкретная конечная точка, с которой я получаю успешный ответ в curl и httpx, но 401 Unauthorized usingurllib.request
.
Сценарий bash, демонстрирующий то, чего я пытаюсь достичь, следующий. Он извлекает токен доступа из API реестра, а затем использует этот токен, чтобы убедиться, что API действительно работает с версией 2, и пытается получить доступ к определенной конфигурации образа Docker. Боюсь, что для проверки вам понадобится доступ к приватному изображению GCR и дайджест для одного из тегов.
#!/usr/bin/env bash
set -eu
token=$(gcloud auth print-access-token)
image=...
digest=sha256:...
get_token() {
curl -sSL \
-G \
--http1.1 \
-H "Authorization: Bearer ${token}" \
-H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
--data-urlencode "scope=repository:$1:pull" \
--data-urlencode "service=gcr.io" \
"https://gcr.io/v2/token" | jq -r '.token'
}
echo "---"
echo "Retrieving access token."
access_token=$(get_token ${image})
echo
echo "---"
echo "Testing version 2 capability with access token."
curl -sSL \
--http1.1 \
-o /dev/null \
-w "%{http_code}" \
-H "Authorization: Bearer ${access_token}" \
-H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
https://gcr.io/v2/
echo
echo "---"
echo "Retrieving image configuration with access token."
curl -vL \
--http1.1 \
-o /dev/null \
-w "%{http_code}" \
-H "Authorization: Bearer ${access_token}" \
-H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
"https://gcr.io/v2/${image}/blobs/${digest}"
Я дополнительно создал два ноутбука Jupyter, демонстрируя свои решения вhttpx
и голый urllib.request
. Httpx работает отлично, в то время как urllib почему-то не выполняет запрос конфигурации изображения. У меня заканчиваются идеи, пытаясь найти разницу. Если вы запустите записную книжку самостоятельно, вы увидите, что вызываемый URL-адрес содержит токен в качестве параметра запроса (это проблема безопасности?). Когда я открываю эту ссылку, я могу успешно загрузить данные самостоятельно. Может быть, urllib по-прежнему передает заголовок авторизации с токеном-носителем, из-за чего последний вызов завершается с ошибкой 401 Unauthorized?
Приветствуются любые идеи.
1 ответ
Я провел небольшое расследование и считаю, что разница в том, что последний звонок "https://gcr.io/v2/${image}/blobs/${digest}"
на самом деле содержит перенаправление. Осмотрcurl
а также httpx
звонки показали мне, что оба не включают Authorization
заголовок во втором перенаправленном запросе, тогда как в том способе, которым я настроил urllib.request
в записной книжке этот заголовок всегда включен. Немного странно, что это приводит к 401, но теперь я знаю, как с этим бороться.
Изменить: теперь я могу подтвердить это, построив urllib.request.Request
экземпляр и в отличие от связанной записной книжки, добавьте заголовок авторизации с запросом add_unredirected_header
метод, все работает как положено.