Python · API · Начальный уровень

Перенаправления

5 задач

Разберитесь с HTTP-перенаправлениями, проверяйте цепочки редиректов и управляйте их обработкой.

Как работают HTTP-перенаправления

#
Когда вы запрашиваете URL, сервер может ответить перенаправлением вместо данных — сигналом, который говорит: «ресурс теперь находится в другом месте, перейдите туда». Два наиболее важных кода перенаправления: - 301 Moved Permanently — URL изменился навсегда. Браузеры и скрипты должны обновить свои закладки. - 302 Found (временное перенаправление) — ресурс временно находится по другому URL. В следующий раз используйте оригинальный URL. Оба кода сопровождаются заголовком Location, который указывает клиенту, куда идти дальше. Библиотека requests следует за перенаправлениями автоматически. Когда вы получаете ответ, вы уже прибыли к конечному назначению: ```python import requests BASE_URL = 'https://apilearn.tukas.dev' response = requests.get(f'{BASE_URL}/api/redirect/') print(response.status_code) # 200 — конечный ответ print(response.url) # https://apilearn.tukas.dev/api/products/ ``` Чтобы увидеть само перенаправление, а не конечный ответ, передайте allow_redirects=False: ```python response = requests.get(f'{BASE_URL}/api/redirect/', allow_redirects=False) print(response.status_code) # 302 print(response.headers['Location']) # куда перенаправляет ``` Когда requests следует за цепочкой перенаправлений, он сохраняет промежуточные ответы в response.history — списке объектов Response, по одному на каждый переход: ```python response = requests.get(f'{BASE_URL}/api/redirect/') for hop in response.history: print(hop.status_code, hop.url) # 302 https://apilearn.tukas.dev/api/redirect/ print(response.status_code, response.url) # 200 финальный URL ``` response.history пустой, если перенаправлений не было. response.url всегда показывает финальный URL, на котором вы оказались, независимо от количества переходов.

Работа с перенаправлениями на практике

#
Сравните временное и постоянное перенаправление: ```python import requests BASE_URL = 'https://apilearn.tukas.dev' # Временное перенаправление (302) r302 = requests.get(f'{BASE_URL}/api/redirect/', allow_redirects=False) print(r302.status_code) # 302 print(r302.headers['Location']) # /api/products/ # Постоянное перенаправление (301) r301 = requests.get(f'{BASE_URL}/api/redirect/permanent/', allow_redirects=False) print(r301.status_code) # 301 print(r301.headers['Location']) # /api/products/ ``` Оба ведут в одно место — разница в коде статуса и что он сигнализирует клиентам. Обзор цепочки перенаправлений через response.history: ```python response = requests.get(f'{BASE_URL}/api/redirect/chain/3/') print(f'Переходов: {len(response.history)}') for i, hop in enumerate(response.history, 1): print(f' {i}. {hop.status_code} {hop.url}') print(f'Финал: {response.status_code} {response.url}') ``` Каждый шаг в цепочке — отдельное перенаправление. Эндпоинт /api/redirect/chain/{steps}/ генерирует ровно N промежуточных переходов перед посадкой на /api/products/. Зачем вообще отключать следование за перенаправлениями? Несколько реальных причин: - Вы хотите проверить заголовок Location перед тем, как следовать за ним. - Нужно определить, перенаправляет ли URL вообще (например, при валидации URL). - Вы реализуете краулер и хотите явно управлять тем, за какими перенаправлениями следовать. - Вы тестируете поведение перенаправления в собственном приложении. Для повседневного получения данных стандартное значение (allow_redirects=True) почти всегда является правильным.

Справочник перенаправлений

#
Эндпоинты перенаправлений: ``` GET /api/redirect/ 302 → /api/products/ GET /api/redirect/permanent/ 301 → /api/products/ GET /api/redirect/chain/{n}/ n перенаправлений (302 каждое) → /api/products/ n должно быть от 1 до 10 ``` Атрибуты ответа, связанные с перенаправлениями: ``` response.status_code Финальный код статуса (200, если следовали автоматически) response.url Финальный URL, на котором вы оказались response.history Список промежуточных Response-объектов (пустой без перенаправлений) response.history[0].url URL первого перенаправления ``` Отключение автоматического следования: ```python response = requests.get(url, allow_redirects=False) # response.status_code теперь 301 или 302 # response.headers['Location'] содержит целевой URL перенаправления ``` Распространённые коды статуса для перенаправлений: ``` 301 Moved Permanently URL изменился навсегда; обновите сохранённые ссылки 302 Found Временное перемещение; сохраняйте оригинальный URL ```
01

Следовать за перенаправлением

#

Отправьте GET-запрос к /api/redirect/ (со стандартным следованием за перенаправлениями). Выведите финальный код статуса и URL, на котором вы оказались.

import requests

BASE_URL = 'https://apilearn.tukas.dev'

# Следуйте за перенаправлением и выведите status_code и финальный URL
Решение
import requests

BASE_URL = 'https://apilearn.tukas.dev'

response = requests.get(f'{BASE_URL}/api/redirect/')
print(response.status_code)
print(response.url)
02

Увидеть само перенаправление

#

Отправьте GET к /api/redirect/ с allow_redirects=False. Выведите код статуса и заголовок Location.

import requests

BASE_URL = 'https://apilearn.tukas.dev'

# Отключите следование за перенаправлениями и проверьте ответ
Решение
import requests

BASE_URL = 'https://apilearn.tukas.dev'

response = requests.get(f'{BASE_URL}/api/redirect/', allow_redirects=False)
print(response.status_code)
print(response.headers['Location'])
03

Обзор истории перенаправлений

#

Отправьте GET к /api/redirect/ и выведите все промежуточные ответы из response.history. Для каждого выведите код статуса и URL. Затем выведите финальные код статуса и URL.

import requests

BASE_URL = 'https://apilearn.tukas.dev'

response = requests.get(f'{BASE_URL}/api/redirect/')

# Выведите каждый переход в response.history, затем финальный ответ
Решение
import requests

BASE_URL = 'https://apilearn.tukas.dev'

response = requests.get(f'{BASE_URL}/api/redirect/')

for hop in response.history:
    print(hop.status_code, hop.url)
print(response.status_code, response.url)
04

Подсчитать переходы в цепочке

#

Отправьте GET к /api/redirect/chain/5/ и выведите количество перенаправлений. Затем выведите URL каждого перехода в цепочке.

import requests

BASE_URL = 'https://apilearn.tukas.dev'

response = requests.get(f'{BASE_URL}/api/redirect/chain/5/')

# Выведите количество переходов и каждый URL в цепочке
Решение
import requests

BASE_URL = 'https://apilearn.tukas.dev'

response = requests.get(f'{BASE_URL}/api/redirect/chain/5/')

print(f'Переходов: {len(response.history)}')
for hop in response.history:
    print(hop.url)
05

Сравнить типы перенаправлений

#

Сравните /api/redirect/ и /api/redirect/permanent/ рядом. Для каждого используйте allow_redirects=False и выведите код статуса.

import requests

BASE_URL = 'https://apilearn.tukas.dev'

# Проверьте коды статуса обоих типов перенаправлений без следования
Решение
import requests

BASE_URL = 'https://apilearn.tukas.dev'

r_temp = requests.get(f'{BASE_URL}/api/redirect/', allow_redirects=False)
r_perm = requests.get(f'{BASE_URL}/api/redirect/permanent/', allow_redirects=False)

print(f'/api/redirect/           → {r_temp.status_code}')
print(f'/api/redirect/permanent/ → {r_perm.status_code}')