Почему Request.build_absolute_uri приводит к localhost вместо реального домена?

У меня есть сайт, развернутый на Nginx и построенный на Django. Ссылка Request.build_absolute_uri там почему-то ведет не на реальный домен и ip, который к нему привязан, а на localhost:8080 из Waitress/gunicorn, на котором запущено приложение. Почему? Я пробовал Request.build_absolute_uri и request._current_scheme_host - оба ведут на localhost. Сейчас временно я просто использую прямой путь типа "domain.com", но это не очень удобное решение.

Не могли бы вы сообщить мне, как решить эту проблему?

После того, как я понял, что передача запросов по всему окружению только для построения полных урлов была беспорядочной, я переделал функцию, используемую для построения абсолютных урлов. Вы просто устанавливаете HOSTNAME в настройках разное имя хоста для каждого окружения.

def build_base_uri():
    return getattr(settings, "USED_PROTOCOL", "http://") + getattr(settings, "HOSTNAME", "localhost")


def build_absolute_url(url):
    return build_base_uri() + url

Если вы хотите придерживаться методов request, я изучил исходный код этого приложения и вот как оно определяет хост, который будет использоваться в uri. (при условии, что у вас нет DEBUG и ваши ALLOWED_HOSTS настроены правильно)

class HttpRequest:
    ...

    def _get_raw_host(self):
        """
        Return the HTTP host using the environment or request headers. Skip
        allowed hosts protection, so may return an insecure host.
        """
        # We try three options, in order of decreasing preference.
        if settings.USE_X_FORWARDED_HOST and (
                'HTTP_X_FORWARDED_HOST' in self.META):
            host = self.META['HTTP_X_FORWARDED_HOST']
        elif 'HTTP_HOST' in self.META:
            host = self.META['HTTP_HOST']
        else:
            # Reconstruct the host using the algorithm from PEP 333.
            host = self.META['SERVER_NAME']
            server_port = self.get_port()
            if server_port != ('443' if self.is_secure() else '80'):
                host = '%s:%s' % (host, server_port)
        return host

В соответствии с этим проверьте в просмотре эти заголовки HTTP_X_FORWARDED_HOST или HTTP_HOST или SERVER_NAME. Если эти заголовки по какой-то причине содержат localhost или отсутствуют, вы можете изучить вопрос в конфигурации nginx о передаче заголовков вниз.

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