Opened 2 years ago

Closed 2 years ago

Last modified 2 years ago

#33362 closed Bug (invalid)

ALLOWED_HOSTS no longer accepts a non-list/tuple iterable.

Reported by: Carlton Gibson Owned by: nobody
Component: HTTP handling Version: 4.0
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

cdd0b213a825fcfe90ae93dcc554fba8c1e5ff5d added ALLOWED_HOSTS to the list of tuple_settings that are checked to be lists or tuples in Settings.__init__().

This causes a regression with settings such as:

class AllowedHosts:
    """
    An allowed hosts proxy, implementing SOME logic to determine ALLOWED_HOSTS.
    """

    DEBUG_ALLOWED_HOSTS = ["localhost", "127.0.0.1", "[::1]"]

    def __iter__(self):
        if settings.DEBUG:
            yield from self.DEBUG_ALLOWED_HOSTS

        yield "domain.com"
        yield "domain.org"
        yield from [
            "other-domain.com",
            "www.other-domain.com",                                                                                         
        ]
        
ALLOWED_HOSTS = AllowedHosts()

This works fine before Django 4.0 but raises afterwards:

raise ImproperlyConfigured("The %s setting must be a list or a tuple." % setting)
django.core.exceptions.ImproperlyConfigured: The ALLOWED_HOSTS setting must be a list or a tuple.

We could revert cdd0b213a825fcfe90ae93dcc554fba8c1e5ff5d, or else adjust the test. I think the force of it is "iterable() but not a string"? 🤔

Change History (5)

comment:1 by Mariusz Felisiak, 2 years ago

Resolution: invalid
Status: newclosed

It's documented that ALLOWED_HOSTS is "a list of strings representing...", it was also discussed in one of PRs. I wouldn't consider it as a regression, sorry :) I'm of course open to discussion.

comment:2 by Carlton Gibson, 2 years ago

OK, we can say that 😜
(It’s worked this way since ≈forever, so it is a change in behaviour, but there’ll be another way.)

comment:3 by Adam Johnson, 2 years ago

There's nothing complicated about your class there, it can be determined at import time right? It only depends on whether DEBUG is True or not.

You could always make your setting a subclass of list and override __iter__ if really required.

comment:4 by Carlton Gibson, 2 years ago

The example is simplified, but I can work around, yes. I do feel we've cut out a legitimate use-case with an overly strict test — it demands more than we need — but it's not something I want to spend time pushing on now. (Not a problem!)

comment:5 by Claude Paroz, 2 years ago

I agree with Carlton, those checks are not totally Pythonic (duck typing and all...) and could probably be improved.

Note: See TracTickets for help on using tickets.
Back to Top