При разбивке DRF на страницы “следующая” ссылка использует устаревшее имя хоста при входе в GKE — как мне заставить его использовать реальный хост?

Каковы детали вашей проблемы?

Я запускаю API фреймворка Django REST на движке Google Kubernetes (GKE) за входом. Когда я запрашиваю:

https://www.my-api-url.com/api/stores/?page=1&active=true

Я получаю правильные результаты, но разбивка на страницы следующая ссылка создается с использованием устаревшего имени хоста :

https://api-back.my-api-url.com/api/stores/?active=true&page=2

Это имя хоста использовалось в предыдущем ingress, но было удалено. Я просмотрел всю кодовую базу, манифесты Kubernetes и конфигурации ingress и нигде не смог его найти. Я нашел этот связанный с этим вопрос, в котором говорится, что DRF использует имя хоста запроса для пагинатора, но я все еще не могу понять откуда берется этот устаревший хост в настройках GKE /Ingress: Как изменить хост в следующем ключе в разбитом на страницы URL-адресе в django rest framework?

Что вы пробовали и чего ожидали?

Я ожидал, что DRF построит next с помощью www.my-api-url.com. Я проверил и/или попробовал:

  • ALLOWED_HOSTS содержит правильный хост.

  • Переключение USE_X_FORWARDED_HOST (Истина/ложь).

  • Установка SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https').

  • Убедитесь, что для нового входа используется правильный общедоступный хост, и полностью удалите старый.

  • Проверено отсутствие жестко запрограммированных ссылок на api-back.my-api-url.com в манифестах репозитория или K8s.

    Несмотря на это, в ссылке next по-прежнему отображается устаревшее имя хоста.

    Вопрос: При настройке входа в GKE, какой заголовок/ параметр фактически управляет хостом, используемым для разбивки на страницы DRF, и как я могу гарантировать, что next использует реальное общедоступное имя хоста? Если это происходит из перенаправленного заголовка, какой конкретный входной заголовок / конфигурацию я должен установить (или отменить)?

DRF builds pagination links using request.build_absolute_uri(), which depends on the Host header it receives.
If your app is behind a GKE Ingress or Load Balancer, it’s likely not forwarding the original host —
so Django sees your internal service name like api-back.my-api-url.com.

1. In your Django settings.py:

USE_X_FORWARDED_HOST = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

2.In your Ingress annotations, preserve the original host:

nginx.ingress.kubernetes.io/use-forwarded-headers: "true"
nginx.ingress.kubernetes.io/configuration-snippet: |
  proxy_set_header Host $host;
  proxy_set_header X-Forwarded-Host $host;

3.If needed, override DRF’s pagination link generator:

from rest_framework.pagination import PageNumberPagination

class FixedHostPagination(PageNumberPagination):
    def get_next_link(self):
        url = super().get_next_link()
        if url:
            return url.replace('api-back.my-api-url.com', 'www.my-api-url.com')
        return None

Why it happens:

Your ingress or proxy rewrites the Host header to the internal service name.
DRF uses that to build links, so you end up with stale internal URLs.

Вернуться на верх